在前端開發(fā)中組件式開發(fā)方式往往都是需要用到各組件之間數(shù)據(jù)缀踪,狀態(tài)的共享,兄弟組件腾务,父子組件數(shù)據(jù)共享等毕骡。在vue中有vuex,react中有redux岩瘦;在flutter中未巫,狀態(tài)共享的工具很多,redux启昧、bloc叙凡、Provide以及阿里閑魚出的fish_redux。本文中先介紹Provide的基本使用密末。
1. 添加依賴
provide官方已經(jīng)不升級維護握爷,但是還是可以使用它:https://github.com/google/flutter-provide
- pubspec.yaml添加如下依賴,保存自動拉取依賴
dependencies:
provide: ^1.0.2
2. 創(chuàng)建共享數(shù)據(jù)Store
筆者目前是前端開發(fā)严里,用的vue新啼,覺得Provide還有點像vuex,所以把共享數(shù)據(jù)叫Store刹碾,其他人叫Model燥撞,不過這都不重要,把它看成是一個數(shù)據(jù)共享源就行迷帜。
2.1 在lib下新建一個store文件
新建counter.dart
// counter.dart
import 'package:flutter/material.dart';
class Counter with ChangeNotifier { // with相當于混合
int _value = 0;
increment() {
_value++;
notifyListeners(); // 通知用到Counter數(shù)據(jù)的物舒,需要更新
}
int get value => _value; // get方法
}
這樣我們的store
就創(chuàng)建完了,里面有一個初始化的數(shù)據(jù)value
為0戏锹,有increment
方法來改變value
的值.
3. 如何使用Store
上一步創(chuàng)建好我們所需要共享的數(shù)據(jù)類后茶鉴,我們?nèi)绾稳ナ褂媚兀窟@個也有點類似React中的高階組件景用,Provide提供了ProviderNode
方法涵叮,該方法傳入共享數(shù)據(jù)和包裝的Widget,然后會返回一個包裝后的Widget伞插,之后這個組件下的所有頁面數(shù)據(jù)就共享了割粮。
3.1 ProviderNode配置
通過查看編輯器的提示,我們可以知道ProviderNode
需要一個Providers providers
和一個Widget child
媚污。
那我們做如下操作
var providers = new Providers(); // 創(chuàng)建一個providers對象
providers..provide(Provider<Counter>.value(counter)); // 把Store添加到providers中
//main.dart
void main() {
runApp(
ProviderNode(
child: MyApp(),
providers: providers,
)
);
}
class MyApp extends StatelessWidget{...}
4. 頁面中展示共享數(shù)據(jù)
我們將數(shù)據(jù)包裝給頂級的Widget舀瓢,所有的頁面數(shù)據(jù)都會共享這個數(shù)據(jù)。
4.1 在頁面中如何展示共享數(shù)據(jù)呢耗美?
用Provide()構(gòu)造函數(shù)獲取到的對應Store數(shù)據(jù),代碼如下
Widget build(BuildContext context) {
return Container(
child: Provide<Counter>( // 獲取對應Store數(shù)據(jù)狀態(tài)
builder: (BuildContext context, Widget child, Counter counter){
return Text(
'${counter.value}', // counter實例
style: TextStyle(fontSize: 30.0),
);
},
),
)
}
4.2 其他組件改變數(shù)據(jù)
// button
class myButton extends StatelessWidget{
return Container(
child: Container(
child: RaisedButton(
onPressed: () {
Provide.value<Counter>(context).increment(); // 調(diào)用Store中實例的方法改變數(shù)據(jù)
},
child: Text('增加'),
),
),
);
}
最后看下效果
思考
隨著我們項目越來越龐大京髓,我們的數(shù)據(jù)也會越來越多航缀,store數(shù)據(jù)也越多,我們最好是把store單獨拎出來堰怨,統(tǒng)一管理
- lib
- store
- allState // 統(tǒng)一在allState中進行管理
- counter
- moreState
- ...
再在store中新增testTitleStore.dart數(shù)據(jù)
tsetTitleStore主要是在頁面跳轉(zhuǎn)時芥玉,動態(tài)設置頁面的title
- store
// allState.dart
import 'package:provide/provide.dart';
import './counter.dart';
import './testUpdateTitle.dart';
Providers provideAll () {
var counter = Counter();
var providers = Providers();
// 第一種方式
// providers..provide(Provider<Counter>.value(counter))
// ..provide(Provider<TestUpdateTitle>.value(TestUpdateTitle()));
// 第二種方式
providers.provideAll({ // 參數(shù)是一個Map key是Provider的類型,value是provider
Counter: Provider<Counter>.value(counter),
TestUpdateTitle: Provider<TestUpdateTitle>.value(TestUpdateTitle()),
});
return providers;
}
main.dart
import './store/allstate.dart';
void main() {
var providers = provideAll();
runApp(
ProviderNode(
child: MyApp(),
providers: providers,
)
);
}
...
點擊頁面跳轉(zhuǎn)备图,觸發(fā)title更新
// 上個頁面
onTap: () {
Provide.value<TestUpdateTitle>(context).updateTitle('各種小練習');
Navigator.of(context).pushNamed('/myInfo');
},
// 下個頁面接受數(shù)據(jù)
appBar: AppBar(
title: Provide<TestUpdateTitle>(
builder: (BuildContext context, Widget child, TestUpdateTitle title) {
return Text(
'${title.text}'
);
},
),
),
ok我們來看下效果
附上自己畫的Provide數(shù)據(jù)流向圖
總結(jié)
flutter中數(shù)據(jù)狀態(tài)共享很多灿巧,選擇一個適合自己的就好,本文介紹了Provide的基本用法揽涮,兩個小栗子抠藕,后面可以再照著新增更多的狀態(tài)就可以了,后面再研究下其他的flutter的狀態(tài)管理工具蒋困。如何本文對你有幫助請給一個小小的贊??盾似,如果本文有寫的不對不到位的地方,還請各位大佬在評論區(qū)指點雪标,康桑密達~