Flutter中使用setState時的6個簡單技巧總結(jié)
前言
setState 函數(shù)是在 Flutter 應(yīng)用程序中管理狀態(tài)的最基本方法。以下是一些保持應(yīng)用可維護(hù)性的最佳實踐。
StatefulWidget 的 setState 函數(shù)是一種在 Flutter 應(yīng)用程序中管理狀態(tài)的簡單方法。但是,當(dāng)您希望您的應(yīng)用程序正常工作和高性能時,您需要避免幾個陷阱。以下是您應(yīng)該堅持的一些最佳實踐。
setState 有什么用?
setState 是Flutter發(fā)出 rebuild (重建)當(dāng)前 widget 及其后代的方式。在 rebuild 過程中,最新的變量值將被用于創(chuàng)建用戶界面。比方說,一個用戶將一個開關(guān)從打開切換到關(guān)閉。該開關(guān)有一個存儲該值的支持變量,所以在改變之后,它被設(shè)置為 false。開關(guān)本身并不反映這一變化,直到它被重建為新的支持字段值。
- 更改值
- 調(diào)用 setState()
- 用戶界面已更新
??技巧 1:保持## widgets小!
setState 觸發(fā)了對你當(dāng)前所在的小組件的重建。如果你的整個應(yīng)用程序只包含一個widget,那么整個widget將被重建,這將使你的應(yīng)用程序變得緩慢。請看下面的例子。
import 'package:flutter/material.dart';
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
@override
State<Home> createState() => _State();
}
class _State extends State<Home> {
bool _tile1 = false;
bool _tile2 = false;
bool _tile3 = false;
bool _tile4 = false;
bool _tile5 = false;
@override
Widget build(BuildContext context) {
print("built method Home"); // <-- setState triggers build here!
return Scaffold(
appBar: AppBar(title: const Text("Demo")),
body: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SwitchListTile(
activeColor: Colors.green,
inactiveThumbColor: Colors.red,
title: Text("Switch is ${_tile1 ? "on" : "off"}"),
value: _tile1,
onChanged: (_) {
setState(() {
_tile1 = !_tile1;
});
}),
SwitchListTile(
activeColor: Colors.green,
inactiveThumbColor: Colors.red,
title: Text("Switch is ${_tile2 ? "on" : "off"}"),
value: _tile2,
onChanged: (_) {
setState(() {
_tile2 = !_tile2;
});
}),
SwitchListTile(
activeColor: Colors.green,
inactiveThumbColor: Colors.red,
title: Text("Switch is ${_tile3 ? "on" : "off"}"),
value: _tile3,
onChanged: (_) {
setState(() {
_tile3 = !_tile3;
});
}),
SwitchListTile(
activeColor: Colors.green,
inactiveThumbColor: Colors.red,
title: Text("Switch is ${_tile4 ? "on" : "off"}"),
value: _tile4,
onChanged: (_) {
setState(() {
_tile4 = !_tile4;
});
}),
SwitchListTile(
activeColor: Colors.green,
inactiveThumbColor: Colors.red,
title: Text("Switch is ${_tile5 ? "on" : "off"}"),
value: _tile5,
onChanged: (_) {
setState(() {
_tile5 = !_tile5;
});
})
])));
}
}這里我們在一個 Column 中有 5 個 SwitchListTile 小部件,它們都是同一個小部件的一部分。
如果您切換任何控件,整個屏幕都會被重建。 Scaffold, AppBar, Column, ... 但只要重建已更改的小部件就足夠了。讓我們看下一個代碼示例:
import 'package:flutter/material.dart';
class Home2 extends StatefulWidget {
const Home2({Key? key}) : super(key: key);
@override
State<Home2> createState() => _State();
}
class _State extends State<Home2> {
@override
Widget build(BuildContext context) {
print("built method Home2");
return Scaffold(
appBar: AppBar(title: const Text("Demo")),
body: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: const <Widget>[
Switch(),
Switch(),
Switch(),
Switch(),
Switch()
])));
}
}
class Switch extends StatefulWidget {
const Switch({Key? key}) : super(key: key);
@override
State<StatefulWidget> createState() => _SwitchState();
}
class _SwitchState extends State<Switch> {
bool _value = false;
@override
Widget build(BuildContext context) {
print("build method Switch"); // <-- setState triggers build here!
return SwitchListTile(
activeColor: Colors.green,
inactiveThumbColor: Colors.red,
title: Text("Switch is ${_value ? "on" : "off"}"),
value: _value,
onChanged: (_) {
setState(() {
_value = !_value;
});
});
}
}在這里,我們將 SwitchListTile 包裝在單個 StatefulWidget 中。頁面看起來相同,但如果您單擊此示例中的任何開關(guān),則只有單擊的小部件將重建。
??技巧 2:不要在構(gòu)建方法中調(diào)用 setState
這個方法有可能在每一幀中被調(diào)用,除了建立一個小部件外,不應(yīng)該有任何副作用。
build 方法旨在構(gòu)建小部件樹,因此我們應(yīng)該保持這種方式。不要在這里做花哨的事情,它會減慢你的應(yīng)用程序。對setState的調(diào)用可能會觸發(fā)額外的重建,在最壞的情況下,你可能最終會出現(xiàn)一個異常,告訴你目前有一個重建正在進(jìn)行。
??技巧 3:不要在 initState 方法中調(diào)用 setState
initState 將在完成后觸發(fā)重建,因此無需在此方法中調(diào)用 setState。此方法旨在初始化與狀態(tài)相關(guān)的屬性,例如設(shè)置默認(rèn)值或訂閱流。不要在這里做任何其他事情!
??技巧4:setState()和setState(...)是相等的
像這樣使用 setState 沒關(guān)系
setState((){
_text = “Hello”;
});或者像這樣
_text = “Hello”;
setState((){});結(jié)果是一樣的。
??技巧 5:setState(...) 代碼必須很小
不要在setState內(nèi)做任何大的計算,因為它將阻止你的應(yīng)用程序重繪。請看下面的示例代碼:
setState(() {
for (var i = 0; i < 10000; i++) print(i);
_value = true;
});只有在打印語句之后,小部件才會重建。在這段時間里,你的應(yīng)用程序不會對用戶的操作做出反應(yīng),它將在之后執(zhí)行這些操作。因此,如果用戶因為沒有視覺反饋而多次點擊一個控件,多次重建就會堆積起來,會使應(yīng)用程序的速度更慢。
一個更好的方法是在執(zhí)行一個長期運行的操作時顯示一個進(jìn)度指示器,這樣用戶就知道正在發(fā)生一些事情,他需要等待完成。
??技巧 6:setState(...) 代碼不能是異步的
運行代碼時
setState(() async {
await Future.delayed(const Duration(seconds: 5));
});你最終會得到一個類似這樣的異常信息:

在方法之外執(zhí)行異步操作,然后調(diào)用它。
結(jié)束
我希望這些見解能幫助你更好地理解Flutter中setState的機制。堅持這些技巧,你會有更少的問題和更快的應(yīng)用程序。源代碼例子可以在GitHub上找到。
到此這篇關(guān)于Flutter中使用setState時的6個簡單技巧的文章就介紹到這了,更多相關(guān)Flutter使用setState的技巧內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android Studio多渠道打包、自定義打包APK名稱
Android Studio為我們提供了簡便的方法,可以多渠道打包,一次打包所有的渠道包。這篇文章主要介紹了Android Studio多渠道打包、自定義打包APK名稱,需要的朋友可以參考下2018-01-01
Android Studio 升級到3.0 提示 java.lang.NoClassDefFoundError的解決方法
這篇文章主要介紹了Android Studio 升級到3.0 提示 java.lang.NoClassDefFoundError的解決方法,需要的朋友可以參考下2017-12-12
android表格效果之ListView隔行變色實現(xiàn)代碼
首先繼承SimpleAdapter再使用重載的Adapter來達(dá)到效果,其實主要是需要重載SimpleAdapter,感興趣的朋友可以研究下,希望本文可以幫助到你2013-02-02
Android ListView在Fragment中的使用示例詳解
這篇文章主要介紹了Android ListView在Fragment中的使用,因為工作一直在用mvvm框架,因此這篇文章是基于mvvm框架寫的,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-09-09
Android中通過訪問本地相冊或者相機設(shè)置用戶頭像實例
本篇文章主要介紹了Android中通過訪問本地相冊或者相機設(shè)置用戶頭像,具有一定的參考價值,有興趣的可以了解一下。2017-01-01

