在flutter中,繼承StatelessWidget的部件狀態(tài)都是不可變的蚤告,也就是部件一旦被創(chuàng)建真慢,里面的數(shù)據(jù)就不會發(fā)生變化,繼承StatefulWidget的部件持有的狀態(tài)可能在widget生命周期中發(fā)生變化. 實現(xiàn)一個 stateful widget 至少需要兩個類:
1邑退、一個 StatefulWidget類。
2劳澄、一個 State類地技。 StatefulWidget類本身是不變的,但是 State類在widget生命周期中始終存在.
部件的狀態(tài)可以自己管理秒拔,也可以從父輩那里傳遞過來莫矗。在父輩管理部件的狀態(tài)時,部件的數(shù)據(jù)是從父輩傳遞過來的砂缩,如果子部件想要改變數(shù)據(jù)作谚,需要從父輩那里傳遞一個回調(diào)進來,如果部件層層嵌套庵芭,就形成了一個部件樹妹懒,數(shù)據(jù)就需要層層傳遞,很麻煩双吆,這種情況下flutter提供了兩種傳遞數(shù)據(jù)的方式:
使用 inheritedWidget
用法是先創(chuàng)建一個 inheritedWidget眨唬,在這個部件里面設(shè)置其他部件需要的數(shù)據(jù)滔悉,然后再把 inheritedWidget放在小部件樹的某一個地方,這樣樹下面的小部件就能直接訪問 inheritedWidget中的數(shù)據(jù)
class StateManagementDemo extends StatefulWidget {
@override
_StateManagementDemoState createState() => _StateManagementDemoState();
}
class _StateManagementDemoState extends State<StateManagementDemo> {
int _count = 0;
void _increaseCount () {
setState(() {
_count += 1;
});
}
@override
Widget build(BuildContext context) {
return CounterProvider(
count: _count,
increaseCount: _increaseCount,
child: Scaffold(
appBar: AppBar(title: Text('StateManagementDemo'), elevation: 0.0,),
body: CounterWrapper(),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: _increaseCount,
),
),
);
}
}
class CounterWrapper extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(child: Counter(),);
}
}
class Counter extends StatelessWidget {
@override
Widget build(BuildContext context) {
final int count = CounterProvider.of(context).count;
final VoidCallback increaseCount = CounterProvider.of(context).increaseCount;
return Center(child: ActionChip(
label: Text('$count'),
onPressed: increaseCount,),
);
}
}
class CounterProvider extends InheritedWidget {
final int count;
final VoidCallback increaseCount;
final Widget child;
CounterProvider({
this.count,
this.increaseCount,
this.child,
}) : super(child: child);
// 其他部件中可以用這個方法得到小部件內(nèi)的數(shù)據(jù)
static CounterProvider of(BuildContext context) => context.inheritFromWidgetOfExactType(CounterProvider);
// 決定是否通知繼承這個小部件的小部件单绑,當(dāng)這個部件重建以后有時候需要通知繼承這個部件的小部件
@override
bool updateShouldNotify(InheritedWidget oldWidget) {
return true;
}
}
使用三方ScopedModel
使用三方ScopedModel將數(shù)據(jù)傳遞給小部件回官,需要先創(chuàng)建一個model,在model里面添加需要傳遞的數(shù)據(jù)搂橙,然后把model放在小部件樹的某個位置上去設(shè)置一下它的model歉提,這樣在它下面的小部件都可以直接訪問到model里的數(shù)據(jù),小部件要使用model里面的數(shù)據(jù)需要用一個 ScopedModelDescendant 去包裝一下区转,設(shè)置一下model的類型苔巨,然后用一個builder方法返回這個小部件,在小部件里面就可以得到model里面的數(shù)據(jù)了
class StateManagementDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ScopedModel(
model: CounterModel(),
child: Scaffold(
appBar: AppBar(title: Text('StateManagementDemo'), elevation: 0.0,),
body: CounterWrapper(),
floatingActionButton: ScopedModelDescendant<CounterModel>(
rebuildOnChange: false,
builder: (context, _, model) => FloatingActionButton(
child: Icon(Icons.add),
onPressed: model.increaseCount,
),
),
),
);
}
}
class Counter extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ScopedModelDescendant<CounterModel>(
builder: (context, _, model) => ActionChip(label: Text('${model.count}'), onPressed: model.increaseCount)
);
}
}
class CounterModel extends Model {
int _count = 0;
int get count => _count;
void increaseCount() {
_count += 1;
// 使用model的小部件會監(jiān)聽model的變化废离,使用這個方法之后侄泽,監(jiān)聽的小部件就會被重建
notifyListeners();
}
}