import ‘package:scoped_model/scoped_model.dart’;
class CounterModel extends Model {
int _counter = 0;
int get counter => _counter;
void increment() {
_counter++;
notifyListeners();
}
void decrement() {
_counter–;
notifyListeners();
}
}
其中数据变化的部分会通知listeners, 它们收到通知后会rebuild.
在上层初始化并提供数据类, 用ScopeModel
.
访问数据有两种方法:
-
用
ScopedModelDescendant
包裹widget. -
用
ScopedModel.of
静态方法.
使用的时候注意要提供泛型类型, 会帮助我们找到离得最近的上层ScopedModel
.
ScopedModelDescendant(
builder: (context, child, model) {
return Text(
model.counter.toString(),
);
}),
数据改变后, 只有ScopedModelDescendant
会收到通知, 从而rebuild.
ScopedModelDescendant
有一个rebuildOnChange
属性, 这个值默认是true.
对于button来说, 它只是控制改变, 自身并不需要重绘, 可以把这个属性置为false.
ScopedModelDescendant(
rebuildOnChange: false,
builder: (context, child, model) {
return FloatingActionButton(
onPressed: model.increment,
tooltip: ‘Increment’,
child: Icon(Icons.add),
);
},
),
scoped model这个库帮我们解决了数据访问和通知的问题, 但是rebuild范围需要自己控制.
-
access state
-
notify other widgets
-
minimal rebuild -> X -> 因为需要开发者自己来决定哪一部分是否需要被重建, 容易被忘记.
代码分支: scoped-model
Provider
Provider是官方文档的例子用的方法.
去年的Google I/O 2019也推荐了这个方法.
和BLoC的流式思想相比, Provider是一个观察者模式, 状态改变时要notifyListeners()
.
有一个counter版本的sample: https://github.com/flutter/samples/tree/master/provider_counter
Provider的实现在内部还是利用了InheritedWidget
.
Provider的好处: dispose指定后会自动被调用, 支持MultiProvider
.
Provider实现
- model类继承
ChangeNotifer
, 也可以用with
.
class CounterModel extends ChangeNotifier {
int value = 0;
void increment() {
value++;
notifyListeners();
}
void decrement() {
value–;
notifyListeners();
}
}
- 数据提供者:
ChangeNotifierProvider
.
void main() => runApp(ChangeNotifierProvider(
create: (context) => CounterModel(),
child: MyApp(),
));
- 数据消费者/操纵者, 有两种方式:
Consumer
包裹, 用Provider.of
.
Consumer(
builder: (context, counter, child) => Text(
‘${counter.value}’,</