【Flutter 專題】46 圖解新的狀態管理 Provider (一)

      網友投稿 741 2025-04-04

      2019 Google I/O 大會上重磅消息出了支持 flutter_web 之外,另一個便是棄用之前的狀態管理 Provide,轉而推薦相似的庫 Provider;雖然只有一個字母之差使用方式差別卻很大;小菜初步學習一下新的狀態管理庫 Provider;

      flutter 針對不同類型對象提供了多種不同的 Provider;Provider 也是借助了 InheritWidget,將共享狀態放到頂層 MaterialApp 之上;

      Provider 方式

      最基本的狀態管理方式,以一個參數方式綁定和展示;

      Provider 可在需要的 Widget 處進行數據綁定:

      const Provider.value({ Key key, @required T value, this.updateShouldNotify, this.child, }) : dispose = null, super.value(key: key, value: value);

      分析源碼 Provider.value 并沒有限制 value 類型,我們可以根據需求隨意綁定需要的數據類型;當我們確定綁定的數據類型時,建議綁定時添加數據類型,如:Provider.value( value: ‘’, child:);

      class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData(primarySwatch: Colors.blue), home: Provider.value( value: 'FirstPage Provider', child: MyHomePage(title: 'Peovider Demo'))); } }

      Provider 需要在數據綁定的子 Widget 中進行獲??;使用靜態方法 Provider.of(BuildContext context),此方法從 BuildContext 關聯的 Widget Tree 中查找最近的相同類型的數據進行展示;沒有則報異常;

      【Flutter 專題】46 圖解新的狀態管理 Provider (一)

      Text('${Provider.of(context)}'), Text('FirstPage Provider: ${Provider.of(context)} | ${Provider.of(context)} | ${Provider.of(context)}}'),

      在我們實際開發中不會只綁定一條數據,當綁定多條數據時可以采用如下兩種方式:嵌套綁定和聚合綁定;兩種方式效果完全相同,小菜更傾向于 MultiProvider 綁定,層級更清晰簡潔;

      // 嵌套綁定 class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData(primarySwatch: Colors.blue), home: Provider.value( value: new User('Flutter', 300), child: Provider.value( value: 200, child: Provider.value( value: false, child: MyHomePage(title: 'Peovider Demo'))))); } } // 聚合方式 class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData(primarySwatch: Colors.blue), home: MultiProvider(providers: [ Provider.value(value: new User('Flutter', 300)), Provider.value(value: 200), Provider.value(value: false) ], child: MyHomePage(title: 'Peovider Demo'))); } }

      Provider 綁定數據類型比較靈活,并非只是基本數據類型,小菜定義了一個 User 類,可正常狀態管理;小菜在獲取 User 后重新設置 name 之后獲取的 User 為最新的數據;

      class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData(primarySwatch: Colors.blue), home: MultiProvider(providers: [ Provider.value(value: new User('Flutter', 300)), Provider.value(value: 200), Provider.value(value: false) ], child: MyHomePage(title: 'Peovider Demo'))); } } Text( 'FirstPage Provider: ${Provider.of(context)} | ' '${Provider.of(context)} | ${Provider.of(context)} | ${Provider.of(context).name = 'Hello World!'}', style: TextStyle(color: Colors.redAccent)), Text('${Provider.of(context).name}'),

      小菜在剛開始學習時被作用域卡到,實際文檔說的很明白,獲取綁定數據的范圍是在綁定數據的子 Widget 中;小菜繪制了一下個人理解的基本作用域圖,如有錯誤請多多指導;

      void main() => runApp() 為范圍最廣的 application 作用域,其作用范圍包括各個 Page 之間;FirstPage 中定義的 Provider A 作用在藍色框范圍內,Provider B 作用在粉色框范圍內,SecondPage 中定義的 Provider C 作用在綠色范圍內;超出范圍則不能進行狀態管理;

      如上圖作用域劃分,在 FirstPage 多個作用域的粉色框中,若獲取 String 類型的狀態管理 Provider.value( value: ‘’, child:),首先在粉色作用域中查找,若存在則展示粉色框中綁定數據;若沒有則查找上一層藍色作用域,存在則為藍色框綁定數據;若依然沒有查找 application 作用域,存在則展示 application 作用域綁定數據;若均沒有則報異常;

      這也驗證了文檔中提及的子 Widget 作用域,一層一層往外層查找,直到可以正常獲?。?/p>

      ChangeNotifierProvider 方式

      通過調用 ChangeNotifier.notifyListeners 對 ChangeNotifier 進行監聽,將其公開給它的子 Widget 并重建依賴項;

      ChangeNotifierProvider 綁定數據有兩種方式:

      ChangeNotifierProvider({Key key, @required ValueBuilder builder, Widget child })

      通過構造器創建一個 ChangeNotifier,在 ChangeNotifierProvider 移除時自動處理;

      class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return ChangeNotifierProvider( builder: (_) => User('Flutter', 0), child: MaterialApp( title: 'Flutter Demo', theme: ThemeData(primarySwatch: Colors.blue), home: MyHomePage(title: 'Peovider Demo'))); } }

      ChangeNotifierProvider.value({Key key, @required T notifier, Widget child })

      通過監聽通知給子 Widget 并重建依賴項;

      class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return ChangeNotifierProvider.value( notifier: User('Flutter', 0), child: MaterialApp( title: 'Flutter Demo', theme: ThemeData(primarySwatch: Colors.blue), home: MyHomePage(title: 'Peovider Demo'))); } }

      獲取數據的方式與直接使用 Provider 相似;

      Text('${Provider.of(context).getName}'),

      相對于 Provider,ChangeNotifierProvider 方式更加靈活,可以通過重寫 get/set 方法來對狀態管理進行修改和使用;

      // User 實體 Bean class User with ChangeNotifier { var name; var age; User(this.name, this.age); void setName(String name) { this.name = name; notifyListeners(); } String get getName => this.name; } // 綁定 Provider class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return ChangeNotifierProvider( builder: (_) => User('Flutter', 0), child: MaterialApp( title: 'Flutter Demo', theme: ThemeData(primarySwatch: Colors.blue), home: MyHomePage(title: 'Peovider Demo'))); } } // 獲取 Provider 數據 Expanded( child: TextField( onChanged: (changed) => Provider.of(context).setName(changed), controller: _phonecontroller, decoration: InputDecoration( hintText: '請輸入用戶名', suffixIcon: IconButton( icon: Icon(Icons.clear, color: Colors.black45), onPressed: () { _phonecontroller.clear(); })))), Text('${Provider.of(context).getName}'),

      問題小結

      小菜在開始嘗試時總是遇到如下問題,Could not find the correct Provider… 測試后了解是在子 Widget 中層級查找未找到對應的綁定數據;極有可能是綁定數據的 Widget 位置未綁定或綁定位置錯誤;

      小菜對 Provider 的理解還很淺顯,對于其他 Provider 的使用還未嘗試;如有錯誤請多多指導!

      來源:阿策小和尚

      Flutter 數據結構

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:在WPS表格中怎么啟用宏功能教程(wps表格怎么開啟宏功能)
      下一篇:Cloud Foundry介紹
      相關文章
      亚洲国产精品免费视频| 亚洲高清最新av网站| 亚洲国产综合无码一区二区二三区 | 中文字幕亚洲精品资源网| 夜夜春亚洲嫩草影院| 亚洲精品亚洲人成在线观看下载| 亚洲乱色伦图片区小说| 亚洲天然素人无码专区| 激情内射亚洲一区二区三区爱妻| 亚洲免费观看网站| 最新国产精品亚洲| 亚洲国产欧美日韩精品一区二区三区| 在线观看日本亚洲一区| 中文日韩亚洲欧美制服| 亚洲第一成年免费网站| 亚洲第一se情网站| 亚洲精品无码久久毛片| 狠狠亚洲婷婷综合色香五月排名| 国产亚洲大尺度无码无码专线 | 亚洲精品国产自在久久| 国产成人精品日本亚洲专区| 国产gv天堂亚洲国产gv刚刚碰 | 亚洲综合小说另类图片动图| 亚洲精品无码中文久久字幕| 精品亚洲成A人在线观看青青| 亚洲AV日韩精品一区二区三区| 亚洲一级片免费看| 九月丁香婷婷亚洲综合色| 亚洲AV无码国产精品麻豆天美| 亚洲人成在线观看| 亚洲人成人77777网站不卡| 2020国产精品亚洲综合网| 亚洲中文字幕乱码熟女在线| 国产亚洲一卡2卡3卡4卡新区| 高清在线亚洲精品国产二区| 国产亚洲美女精品久久久| 亚洲国产精品乱码一区二区 | 亚洲精品老司机在线观看| 亚洲日韩精品A∨片无码| 亚洲成人在线网站| 亚洲AV成人无码天堂|