Flutter中使用setState時(shí)的6個(gè)簡單技巧總結(jié)
前言
setState 函數(shù)是在 Flutter 應(yīng)用程序中管理狀態(tài)的最基本方法。以下是一些保持應(yīng)用可維護(hù)性的最佳實(shí)踐。
StatefulWidget 的 setState 函數(shù)是一種在 Flutter 應(yīng)用程序中管理狀態(tài)的簡單方法。但是,當(dāng)您希望您的應(yīng)用程序正常工作和高性能時(shí),您需要避免幾個(gè)陷阱。以下是您應(yīng)該堅(jiān)持的一些最佳實(shí)踐。
setState 有什么用?
setState 是Flutter發(fā)出 rebuild (重建)當(dāng)前 widget 及其后代的方式。在 rebuild 過程中,最新的變量值將被用于創(chuàng)建用戶界面。比方說,一個(gè)用戶將一個(gè)開關(guān)從打開切換到關(guān)閉。該開關(guān)有一個(gè)存儲(chǔ)該值的支持變量,所以在改變之后,它被設(shè)置為 false。開關(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 中。頁面看起來相同,但如果您單擊此示例中的任何開關(guān),則只有單擊的小部件將重建。
??技巧 2:不要在構(gòu)建方法中調(diào)用 setState
這個(gè)方法有可能在每一幀中被調(diào)用,除了建立一個(gè)小部件外,不應(yīng)該有任何副作用。
build 方法旨在構(gòu)建小部件樹,因此我們應(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ā)重建,因此無需在此方法中調(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)做任何大的計(jì)算,因?yàn)樗鼘⒆柚鼓愕膽?yīng)用程序重繪。請(qǐng)看下面的示例代碼:
setState(() {
for (var i = 0; i < 10000; i++) print(i);
_value = true;
});只有在打印語句之后,小部件才會(huì)重建。在這段時(shí)間里,你的應(yīng)用程序不會(huì)對(duì)用戶的操作做出反應(yīng),它將在之后執(zhí)行這些操作。因此,如果用戶因?yàn)闆]有視覺反饋而多次點(diǎn)擊一個(gè)控件,多次重建就會(huì)堆積起來,會(huì)使應(yīng)用程序的速度更慢。
一個(gè)更好的方法是在執(zhí)行一個(gè)長期運(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é)束
我希望這些見解能幫助你更好地理解Flutter中setState的機(jī)制。堅(jiān)持這些技巧,你會(huì)有更少的問題和更快的應(yīng)用程序。源代碼例子可以在GitHub上找到。
到此這篇關(guān)于Flutter中使用setState時(shí)的6個(gè)簡單技巧的文章就介紹到這了,更多相關(guān)Flutter使用setState的技巧內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android開發(fā)之計(jì)算器GridLayout布局實(shí)現(xiàn)方法示例
這篇文章主要介紹了Android開發(fā)之計(jì)算器GridLayout布局實(shí)現(xiàn)方法,結(jié)合實(shí)例形式分析了Android計(jì)算器界面布局及表達(dá)式計(jì)算相關(guān)操作技巧,需要的朋友可以參考下2019-03-03
android AsynTask處理返回?cái)?shù)據(jù)和AsynTask使用get,post請(qǐng)求
本文主要介紹了android AsynTask處理返回?cái)?shù)據(jù)和AsynTask使用get,post請(qǐng)求方法。具有一定的參考價(jià)值,下面跟著小編一起來看下吧2017-01-01
Android實(shí)現(xiàn)訂單倒計(jì)時(shí)功能
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)訂單倒計(jì)時(shí)的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-01-01
Android中使用LayoutInflater要注意的一些坑
LayoutInflater類在我們?nèi)粘i_發(fā)中經(jīng)常會(huì)用到,最近在使用中就遇到了一些問題,所有下面這篇文章主要給大家總結(jié)了關(guān)于Android中使用LayoutInflater要注意的一些坑,希望通過這篇能讓大家避免走一些彎路,需要的朋友可以參考學(xué)習(xí),下面來一起看吧。2017-04-04
Android對(duì)so進(jìn)行簡單hook思路解析
這篇文章主要為大家介紹了Android對(duì)so進(jìn)行簡單hook思路解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04
Android自定義扇形倒計(jì)時(shí)實(shí)例代碼
最近工作中需要做一個(gè)倒計(jì)時(shí),是那種一個(gè)圓,慢慢的被吃掉的動(dòng)畫倒計(jì)時(shí),由于自己是android小白,效果還不是多滿意,先給大家分享實(shí)例代碼,僅供大家參考2017-03-03
Android 中使用 dlib+opencv 實(shí)現(xiàn)動(dòng)態(tài)人臉檢測功能
完成 Android 相機(jī)預(yù)覽功能以后,在此基礎(chǔ)上我使用 dlib 與 opencv 庫做了一個(gè)關(guān)于人臉檢測的 demo。接下來通過本文給大家介紹Android 中使用 dlib+opencv 實(shí)現(xiàn)動(dòng)態(tài)人臉檢測功能 ,需要的朋友可以參考下2018-11-11
Flutter實(shí)現(xiàn)Android滾動(dòng)懸浮效果過程
這篇文章主要介紹了Flutter實(shí)現(xiàn)Android滾動(dòng)懸浮效果,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2023-01-01
Android?Flutter實(shí)現(xiàn)"斑馬紋"背景的示例代碼
本文將通過實(shí)現(xiàn)一個(gè)canvas繪制斑馬紋類。使用Stack布局,將斑馬紋放在下方作為背景板,需要展示的內(nèi)容在上方。從而實(shí)現(xiàn)?“斑馬紋”背景,感興趣的可以了解一下2022-06-06

