Flutter 有兩種狀態(tài)控件:StatelessWidget、StatefulWidget,對于有可變狀態(tài)控件的管理,官方文檔是寫了有3種模式:控件自己管理狀態(tài)、交給父控件管理狀態(tài)以及混合管理。我個人初學對于自己管理比較好理解,對于父控件管理理解起來有點困難,所以只能多看多學。這里寫一下兩種狀態(tài)管理的方式和代碼,加深自己的印象,尤其是父控件管理方式。
項目說明:兩種方式實現(xiàn)一個容器盒子,點擊的時候切換顏色和顯示內(nèi)容。我將把這兩個盒子做到一個頁面,雖然最終效果是一樣的,但是實現(xiàn)方式不同。
一、控件自身管理自己的狀態(tài)
/*
TapBoxA 是自身widget管理自己狀態(tài)
*/
class TapBoxA extends StatefulWidget {
@override
_TapBoxAState createState() {
return new _TapBoxAState();
}
}
class _TapBoxAState extends State<TapBoxA> {
bool _aActive = false;
void _aActiveChanged() {
setState(() {
if (_aActive) {
_aActive = false;
} else {
_aActive = true;
}
});
}
@override
Widget build(BuildContext context) {
return new GestureDetector(
onTap: _aActiveChanged,
child: new Center(
child: new Container(
alignment: Alignment.center,
width: 200.0,
height: 200.0,
child: new Text(
_aActive ? 'Active' : 'Inactive',
style: new TextStyle(fontSize: 50.0, color: Colors.white),
),
decoration: new BoxDecoration(
color: _aActive ? Colors.green[400] : Colors.grey),
),
),
);
}
}
二、由父控件管理子控件的狀態(tài)
子控件自身是無狀態(tài)的控件,但是父控件會在子控件發(fā)生變化以后得知這一更新,并進行狀態(tài)的更新以及控件的重繪。
/*
TapBoxB 是父widget管理子widget狀態(tài);
TapBoxB 繼承自無狀態(tài)控件,不管理任何狀態(tài)
*/
class TapBoxB extends StatelessWidget {
TapBoxB({Key key, this.bActive: false, this.onChanged}) : super(key: key);
final bActive;
final ValueChanged<bool> onChanged;
void _bActiveChanged() {
onChanged(!bActive);
}
@override
Widget build(BuildContext context) {
return new GestureDetector(
onTap: _bActiveChanged,
child: new Center(
child: new Container(
alignment: Alignment.center,
width: 200.0,
height: 200.0,
child: new Text(
bActive ? 'Active' : 'Inactive',
style: new TextStyle(fontSize: 50.0, color: Colors.white),
),
decoration: new BoxDecoration(
color: bActive ? Colors.green[400] : Colors.grey),
),
),
);
}
}
/*
ParentWidget類是TapBoxB的父類
他會得知盒子是否被點擊從而管理盒子的狀態(tài),通過setState更新展示內(nèi)容
*/
class ParentWidgetB extends StatefulWidget {
@override
_ParentWidgetBState createState() {
return new _ParentWidgetBState();
}
}
class _ParentWidgetBState extends State<ParentWidgetB> {
bool _bActive = false;
void _handleTapBoxBChanged(bool value) {
setState(() {
_bActive = value;
});
}
@override
Widget build(BuildContext context) {
return new TapBoxB(
bActive: _bActive,
onChanged: _handleTapBoxBChanged,
);
}
}
最后是代碼整合,把上面兩個不同方式實現(xiàn)盒子點擊狀態(tài)更改的代碼在一個APP里展示出來
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'TapBox',
theme: new ThemeData(primaryColor: Colors.white),
home: new Scaffold(
appBar: new AppBar(
title: new Text('TapBox'),
),
body: new Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new TapBoxA(),
new ParentWidgetB(),
],
),
),
);
}
}
運行后首頁顯示如下:

狀態(tài)管理實現(xiàn)1.png
點擊后效果如下(實現(xiàn)方式不同):

Screenshot_20180913-105838.png