Flutter中使用setState時(shí)的6個(gè)簡(jiǎn)單技巧總結(jié)
前言
setState 函數(shù)是在 Flutter 應(yīng)用程序中管理狀態(tài)的最基本方法。以下是一些保持應(yīng)用可維護(hù)性的最佳實(shí)踐。
StatefulWidget 的 setState 函數(shù)是一種在 Flutter 應(yīng)用程序中管理狀態(tài)的簡(jiǎn)單方法。但是,當(dāng)您希望您的應(yīng)用程序正常工作和高性能時(shí),您需要避免幾個(gè)陷阱。以下是您應(yīng)該堅(jiān)持的一些最佳實(shí)踐。
setState 有什么用?
setState 是Flutter發(fā)出 rebuild (重建)當(dāng)前 widget 及其后代的方式。在 rebuild 過(guò)程中,最新的變量值將被用于創(chuàng)建用戶界面。比方說(shuō),一個(gè)用戶將一個(gè)開(kāi)關(guān)從打開(kāi)切換到關(guān)閉。該開(kāi)關(guān)有一個(gè)存儲(chǔ)該值的支持變量,所以在改變之后,它被設(shè)置為 false。開(kāi)關(guān)本身并不反映這一變化,直到它被重建為新的支持字段值。
- 更改值
- 調(diào)用 setState()
- 用戶界面已更新
??技巧 1:保持## widgets??!
setState 觸發(fā)了對(duì)你當(dāng)前所在的小組件的重建。如果你的整個(gè)應(yīng)用程序只包含一個(gè)widget,那么整個(gè)widget將被重建,這將使你的應(yīng)用程序變得緩慢。請(qǐ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; }); }) ]))); } }
這里我們?cè)谝粋€(gè) Column 中有 5 個(gè) SwitchListTile 小部件,它們都是同一個(gè)小部件的一部分。
如果您切換任何控件,整個(gè)屏幕都會(huì)被重建。 Scaffold, AppBar, Column, ... 但只要重建已更改的小部件就足夠了。讓我們看下一個(gè)代碼示例:
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 包裝在單個(gè) StatefulWidget 中。頁(yè)面看起來(lái)相同,但如果您單擊此示例中的任何開(kāi)關(guān),則只有單擊的小部件將重建。
??技巧 2:不要在構(gòu)建方法中調(diào)用 setState
來(lái)自 Flutter API 文檔
這個(gè)方法有可能在每一幀中被調(diào)用,除了建立一個(gè)小部件外,不應(yīng)該有任何副作用。
build 方法旨在構(gòu)建小部件樹(shù),因此我們應(yīng)該保持這種方式。不要在這里做花哨的事情,它會(huì)減慢你的應(yīng)用程序。對(duì)setState的調(diào)用可能會(huì)觸發(fā)額外的重建,在最壞的情況下,你可能最終會(huì)出現(xiàn)一個(gè)異常,告訴你目前有一個(gè)重建正在進(jìn)行。
??技巧 3:不要在 initState 方法中調(diào)用 setState
initState 將在完成后觸發(fā)重建,因此無(wú)需在此方法中調(diào)用 setState。此方法旨在初始化與狀態(tài)相關(guān)的屬性,例如設(shè)置默認(rèn)值或訂閱流。不要在這里做任何其他事情!
??技巧4:setState()和setState(...)是相等的
像這樣使用 setState 沒(méi)關(guān)系
setState((){ _text = “Hello”; });
或者像這樣
_text = “Hello”; setState((){});
結(jié)果是一樣的。
??技巧 5:setState(...) 代碼必須很小
不要在setState內(nèi)做任何大的計(jì)算,因?yàn)樗鼘⒆柚鼓愕膽?yīng)用程序重繪。請(qǐng)看下面的示例代碼:
setState(() { for (var i = 0; i < 10000; i++) print(i); _value = true; });
只有在打印語(yǔ)句之后,小部件才會(huì)重建。在這段時(shí)間里,你的應(yīng)用程序不會(huì)對(duì)用戶的操作做出反應(yīng),它將在之后執(zhí)行這些操作。因此,如果用戶因?yàn)闆](méi)有視覺(jué)反饋而多次點(diǎn)擊一個(gè)控件,多次重建就會(huì)堆積起來(lái),會(huì)使應(yīng)用程序的速度更慢。
一個(gè)更好的方法是在執(zhí)行一個(gè)長(zhǎng)期運(yùn)行的操作時(shí)顯示一個(gè)進(jìn)度指示器,這樣用戶就知道正在發(fā)生一些事情,他需要等待完成。
??技巧 6:setState(...) 代碼不能是異步的
運(yùn)行代碼時(shí)
setState(() async { await Future.delayed(const Duration(seconds: 5)); });
你最終會(huì)得到一個(gè)類似這樣的異常信息:
在方法之外執(zhí)行異步操作,然后調(diào)用它。
結(jié)束
我希望這些見(jiàn)解能幫助你更好地理解Flutter中setState的機(jī)制。堅(jiān)持這些技巧,你會(huì)有更少的問(wèn)題和更快的應(yīng)用程序。源代碼例子可以在GitHub上找到。
到此這篇關(guān)于Flutter中使用setState時(shí)的6個(gè)簡(jiǎn)單技巧的文章就介紹到這了,更多相關(guān)Flutter使用setState的技巧內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android Studio多渠道打包、自定義打包APK名稱
Android Studio為我們提供了簡(jiǎn)便的方法,可以多渠道打包,一次打包所有的渠道包。這篇文章主要介紹了Android Studio多渠道打包、自定義打包APK名稱,需要的朋友可以參考下2018-01-01Android Studio 升級(jí)到3.0 提示 java.lang.NoClassDefFoundError的解決方法
這篇文章主要介紹了Android Studio 升級(jí)到3.0 提示 java.lang.NoClassDefFoundError的解決方法,需要的朋友可以參考下2017-12-12MPAndroidChart 自定義圖表繪制使用實(shí)例
這篇文章主要為大家介紹了MPAndroidChart 自定義圖表繪制使用實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09android表格效果之ListView隔行變色實(shí)現(xiàn)代碼
首先繼承SimpleAdapter再使用重載的Adapter來(lái)達(dá)到效果,其實(shí)主要是需要重載SimpleAdapter,感興趣的朋友可以研究下,希望本文可以幫助到你2013-02-02AndroidQ(10)分區(qū)存儲(chǔ)完美適配方法
這篇文章主要介紹了AndroidQ(10)分區(qū)存儲(chǔ)完美適配方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12Android ListView在Fragment中的使用示例詳解
這篇文章主要介紹了Android ListView在Fragment中的使用,因?yàn)楣ぷ饕恢痹谟胢vvm框架,因此這篇文章是基于mvvm框架寫的,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-09-09Android中通過(guò)訪問(wèn)本地相冊(cè)或者相機(jī)設(shè)置用戶頭像實(shí)例
本篇文章主要介紹了Android中通過(guò)訪問(wèn)本地相冊(cè)或者相機(jī)設(shè)置用戶頭像,具有一定的參考價(jià)值,有興趣的可以了解一下。2017-01-01