大到整个app的状态,用户使用app是登陆状态,仍是游客状态;小到一个按钮的状态,按钮是点击选中状态仍是未点击状态等等,这些都是状态管理。编程
Flutter 应用是 声明式 的,这也就意味着 Flutter 构建的用户界面就是应用的当前状态。bash
一旦你的界面状态发生改变,就会触发界面的从新绘制,绘制出你想要的界面,而不是像iOS的OC语言那样去获取须要改变状态的控件,而后修改它架构
Flutter中的状态管理又分为短时状态和应用状态。app
在下方你能够看到一个底部导航栏中当前被选中的项目是如何被被保存在 _MyHomepageState 类的 _index 变量中。在这个例子中,_index 是一个短时状态。less
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() 和一个变量就能达到管理状态的目的。你的 app 中的其余部分不须要访问 _index。这个变量只会在 MyHomepage widget 中改变。并且,若是用户关闭并重启这个 app,_index会被重置而不会继续保持原来的状态。ide
应用状态,若是你想在你的应用中的多个部分之间共享一个非短时的状态,而且在用户会话期间保留这个状态,咱们称之为应用状态(有时也称共享状态)。 应用状态的一些例子:函数
一、用户选项
二、登陆信息
三、一个社交应用中的通知
四、一个电商应用中的购物车
五、一个新闻应用中的文章已读/未读状态
复制代码
在 Flutter 中,通常是将存储状态的对象置于 widget 树中对应 widget 的上层,当它发生改变的时候,它对应的widget会从上层开始重构。由于这个机制,因此 widget 无需考虑生命周期的问题—它只须要针对 上层存储数据的对象 声明所需显示内容便可。当内容发生改变的时候,旧的 widget 就会消失,彻底被新的 widget 替代。 Flutter原生提供了两个方法来管理共享状态:测试
class ADCounterWidget extends InheritedWidget {
// 1. 共享的数据
final int counter;
// 2. 定义构造方法
ADCounterWidget({this.counter, Widget child}): super(child: child);
// 3. 找到当前Widget树中最近的InheritedWidget
static ADCounterWidget of(BuildContext context) {
// 沿着Element树, 去找到最近的ADCounterElement, 从Element中取出Widget对象
return context.dependOnInheritedWidgetOfExactType();
}
// 4. 要不要回调State中的didChangeDependencies方法
@override
bool updateShouldNotify(ADCounterWidget oldWidget) {
return oldWidget.counter != counter;
}
}
复制代码
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++;
});
},
),
);
}
}
复制代码
建立HYDataWidget,而且传入数据(这里点击按钮会修改数据,而且出发从新build)优化
Provider库有三个主要用到的类:ui
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();
}
}
复制代码
class HYHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("列表测试"),
),
body: Center(
child: Consumer<CounterProvider>(
builder: (ctx, counterPro, child) {
return Text("当前计数:${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方法有三个参数:
class SecondPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("第二个页面"),
),
floatingActionButton: Consumer<CounterProvider>(
builder: (ctx, counterPro, child) {
return FloatingActionButton(
child: child,
onPressed: () {
counterPro.counter += 1;
},
);
},
child: Icon(Icons.add),
),
);
}
}
复制代码