欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Flutter 狀態(tài)管理的實(shí)現(xiàn)

 更新時(shí)間:2020年06月15日 10:43:15   作者:叫我丶華仔  
這篇文章主要介紹了Flutter 狀態(tài)管理的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

一、什么是狀態(tài)管理

大到整個(gè)app的狀態(tài),用戶使用app是登錄狀態(tài),還是游客狀態(tài);小到一個(gè)按鈕的狀態(tài),按鈕是點(diǎn)擊選中狀態(tài)還是未點(diǎn)擊狀態(tài)等等,這些都是狀態(tài)管理。

二、命令式編程和聲明式編程狀態(tài)管理的區(qū)別

iOS是如何管理狀態(tài)的,一般都是獲取這個(gè)控件然后設(shè)置你想要的狀態(tài) 當(dāng)你的 Flutter 應(yīng)用的狀態(tài)發(fā)生改變時(shí)(例如,用戶在設(shè)置界面中點(diǎn)擊了一個(gè)開關(guān)選項(xiàng))你改變了狀態(tài),這將會(huì)觸發(fā)用戶界面的重繪。去改變用戶界面本身是沒有必要的(例如 widget.setText )—你改變了狀態(tài),那么用戶界面將重新構(gòu)建。

三、狀態(tài)管理中的聲明式編程思維

Flutter 應(yīng)用是 聲明式 的,這也就意味著 Flutter 構(gòu)建的用戶界面就是應(yīng)用的當(dāng)前狀態(tài)。

一旦你的界面狀態(tài)發(fā)生改變,就會(huì)觸發(fā)界面的重新繪制,繪制出你想要的界面,而不是像iOS的OC語言那樣去獲取需要改變狀態(tài)的控件,然后修改它

四、短時(shí) (ephemeral) 和應(yīng)用 (app) 狀態(tài)的區(qū)別

Flutter中的狀態(tài)管理又分為短時(shí)狀態(tài)和應(yīng)用狀態(tài)。

短時(shí)狀態(tài),就是在單個(gè)頁面需要保持的狀態(tài),比如頁面數(shù)據(jù)加載到了第幾頁,關(guān)注按鈕是已關(guān)注還是未關(guān)注等,都是在單個(gè)頁面需要保持的狀態(tài)。widget樹中其他部分不需要訪問這種狀態(tài)。不需要去序列化這種狀態(tài),這種狀態(tài)也不會(huì)以復(fù)雜的方式改變。換句話說,不需要使用狀態(tài)管理架構(gòu)(例如 ScopedModel, Redux)去管理這種狀態(tài)。你需要用的只是一個(gè) StatefulWidget。

在下方你可以看到一個(gè)底部導(dǎo)航欄中當(dāng)前被選中的項(xiàng)目是如何被被保存在 _MyHomepageState 類的 _index 變量中。在這個(gè)例子中,_index 是一個(gè)短時(shí)狀態(tài)。

class MyHomepage extends StatefulWidget {
 @override
 _MyHomepageState createState() => _MyHomepageState();
}

class _MyHomepageState extends State<MyHomepage> {
 int _index = 0;

 @override
 Widget build(BuildContext context) {
  return BottomNavigationBar(
   currentIndex: _index,
   onTap: (newIndex) {
    setState(() {
     _index = newIndex;
    });
   },
   // ... items ...
  );
 }
}

在這里,使用 setState() 和一個(gè)變量就能達(dá)到管理狀態(tài)的目的。你的 app 中的其他部分不需要訪問 _index。這個(gè)變量只會(huì)在 MyHomepage widget 中改變。而且,如果用戶關(guān)閉并重啟這個(gè) app,_index會(huì)被重置而不會(huì)繼續(xù)保持原來的狀態(tài)。

應(yīng)用狀態(tài),如果你想在你的應(yīng)用中的多個(gè)部分之間共享一個(gè)非短時(shí)的狀態(tài),并且在用戶會(huì)話期間保留這個(gè)狀態(tài),我們稱之為應(yīng)用狀態(tài)(有時(shí)也稱共享狀態(tài))。 應(yīng)用狀態(tài)的一些例子:

1、用戶選項(xiàng)

2、登錄信息

3、一個(gè)社交應(yīng)用中的通知

4、一個(gè)電商應(yīng)用中的購物車

5、一個(gè)新聞應(yīng)用中的文章已讀/未讀狀態(tài)

五、共享狀態(tài)管理

在 Flutter 中,一般是將存儲(chǔ)狀態(tài)的對(duì)象置于 widget 樹中對(duì)應(yīng) widget 的上層,當(dāng)它發(fā)生改變的時(shí)候,它對(duì)應(yīng)的widget會(huì)從上層開始重構(gòu)。因?yàn)檫@個(gè)機(jī)制,所以 widget 無需考慮生命周期的問題—它只需要針對(duì) 上層存儲(chǔ)數(shù)據(jù)的對(duì)象 聲明所需顯示內(nèi)容即可。當(dāng)內(nèi)容發(fā)生改變的時(shí)候,舊的 widget 就會(huì)消失,完全被新的 widget 替代。 Flutter原生提供了兩個(gè)方法來管理共享狀態(tài):

5.1 --InheritedWidget

class ADCounterWidget extends InheritedWidget {
 // 1. 共享的數(shù)據(jù)
 final int counter;

 // 2. 定義構(gòu)造方法
 ADCounterWidget({this.counter, Widget child}): super(child: child);

 // 3. 找到當(dāng)前Widget樹中最近的InheritedWidget
 static ADCounterWidget of(BuildContext context) {
  // 沿著Element樹, 去找到最近的ADCounterElement, 從Element中取出Widget對(duì)象
  return context.dependOnInheritedWidgetOfExactType();
 }

 // 4. 要不要回調(diào)State中的didChangeDependencies方法
 @override
 bool updateShouldNotify(ADCounterWidget oldWidget) {
  return oldWidget.counter != counter;
 }
}

上面定義了一個(gè)of方法,該方法通過context開始去查找父級(jí)的HYDataWidget

updateShouldNotify方法是對(duì)比新舊HYDataWidget,是否需要對(duì)更新相關(guān)依賴的Widget

class HYHomePage extends StatefulWidget {
 @override
 _HYHomePageState createState() => _HYHomePageState();
}

class _HYHomePageState extends State<HYHomePage> {
 int data = 100;

 @override
 Widget build(BuildContext context) {
  return Scaffold(
   appBar: AppBar(
    title: Text("InheritedWidget"),
   ),
   body: HYDataWidget(
    counter: data,
    child: Center(
     child: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
       HYShowData()
      ],
     ),
    ),
   ),
   floatingActionButton: FloatingActionButton(
    child: Icon(Icons.add),
    onPressed: () {
     setState(() {
      data++;
     });
    },
   ),
  );
 }
}

創(chuàng)建HYDataWidget,并且傳入數(shù)據(jù)(這里點(diǎn)擊按鈕會(huì)修改數(shù)據(jù),并且出發(fā)重新build)

5.2 --Provider

Provider庫有三個(gè)主要用到的類:

  • ChangeNotifier:真正數(shù)據(jù)(狀態(tài))存放的地方
  • ChangeNotifierProvider:Widget樹中提供數(shù)據(jù)(狀態(tài))的地方,會(huì)在其中創(chuàng)建對(duì)應(yīng)的ChangeNotifier
  • Consumer:Widget樹中需要使用數(shù)據(jù)(狀態(tài))的地方

第一步 在程序的最頂層創(chuàng)建自己的ChangeNotifier

  •  將ChangeNotifierProvider放到了頂層,這樣方便在整個(gè)應(yīng)用的任何地方可以使用CounterProvider
  • 在ChangeNotifier中創(chuàng)建一個(gè)私有的_counter,并且提供了getter和setter
  • 在setter中我們監(jiān)聽到_counter的改變,就調(diào)用notifyListeners方法,通知所有的Consumer進(jìn)行更新
void main() {
 runApp(ChangeNotifierProvider(
  create: (context) => CounterProvider(),
  child: MyApp(),
 ));
}

class CounterProvider extends ChangeNotifier {
 int _counter = 100;
 intget counter {
  return _counter;
 }
 set counter(int value) {
  _counter = value;
  notifyListeners();
 }
}

第二步 在首頁中使用Consumer引入和修改狀態(tài)

  • 在body中使用Consumer,Consumer需要傳入一個(gè)builder回調(diào)函數(shù),當(dāng)數(shù)據(jù)發(fā)生變化時(shí),就會(huì)通知依賴數(shù)據(jù)的Consumer重新調(diào)用builder方法來構(gòu)建
  • 在floatingActionButton中使用Consumer,當(dāng)點(diǎn)擊按鈕時(shí),修改CounterNotifier中的counter數(shù)據(jù)
class HYHomePage extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
  return Scaffold(
   appBar: AppBar(
    title: Text("列表測(cè)試"),
   ),
   body: Center(
    child: Consumer<CounterProvider>(
     builder: (ctx, counterPro, child) {
      return Text("當(dāng)前計(jì)數(shù):${counterPro.counter}", style: TextStyle(fontSize: 20, color: Colors.red),);
     }
    ),
   ),
   floatingActionButton: Consumer<CounterProvider>(
    builder: (ctx, counterPro, child) {
     return FloatingActionButton(
      child: child,
      onPressed: () {
       counterPro.counter += 1;
      },
     );
    },
    child: Icon(Icons.add),
   ),
  );
 }
}

Consumer的builder方法有三個(gè)參數(shù):

  • context,每個(gè)build方法都會(huì)有上下文,目的是知道當(dāng)前樹的位置
  • ChangeNotifier對(duì)應(yīng)的實(shí)例,也是我們?cè)赽uilder函數(shù)中主要使用的對(duì)象
  • child,目的是進(jìn)行優(yōu)化,如果builder下面有一顆龐大的子樹,當(dāng)模型發(fā)生改變的時(shí)候,我們并不希望重新build這顆子樹,那么就可以將這顆子樹放到Consumer的child中,在這里直接引入即可(注意我案例中的Icon所放的位置)

第四步 創(chuàng)建一個(gè)新的頁面,在新的頁面中修改數(shù)據(jù)

class SecondPage extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
  return Scaffold(
   appBar: AppBar(
    title: Text("第二個(gè)頁面"),
   ),
   floatingActionButton: Consumer<CounterProvider>(
    builder: (ctx, counterPro, child) {
     return FloatingActionButton(
      child: child,
      onPressed: () {
       counterPro.counter += 1;
      },
     );
    },
    child: Icon(Icons.add),
   ),
  );
 }
}

到此這篇關(guān)于Flutter 狀態(tài)管理的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Flutter 狀態(tài)管理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論