scoped_model
scoped_model 能够让你很方便的传递 Model ,从 parent Widget 到它的后代。另外,当model发生变化可以,它可以重新构建所有的孩子widget。这个库是从 Fuchsia codebase提炼出来的。
该库主要提供了三个主要的类:
-
Model
. 你需要继承这个这个类,来实现你自己的Models,比如SearchModel
或者UserModel
。你可以监听这些model的变化。 -
ScopedModel
Widget。Model
, 你可以把你的model
包装进ScopedModel
Widget。这将会使Model 对所有子孙Widgets可用。 -
ScopedModelDescendant
Widget。使用这个Widget可以让你在Widget树中找到更合适的ScopedModel
。当 Model变化通知者通知变化时,它会自动构建。
这个仓库构建于flutter的一些特征之上:
-
Model
实现了Listenable
接口。AnimationController
和TextEditingController
也都实现了这个接口。 -
Model
可以向Widget树传递 是使用了InheritedWidget
。当InheritedWidget
被重新构建时,会驱动重新构建所有依赖这个数据的Widgets。 - 它使用了
AnimatedBuilder
Widget 在底层,用来监听 Model, 当model变化时会重新构建InheritedWidget
。
Examples
用法
通过上面的 Counter
样例来看看基本用法:
// Start by creating a class that holds some view the app's state. In
// our example, we'll have a simple counter that starts at 0 can be
// incremented.
//
// Note: It must extend from Model.
class CounterModel extends Model {
int _counter = 0;
int get counter => _counter;
void increment() {
// First, increment the counter
_counter++;
// Then notify all the listeners.
notifyListeners();
}
}
// Create our App, which will provide the `CounterModel` to
// all children that require it!
class CounterApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// First, create a `ScopedModel` widget. This will provide
// the `model` to the children that request it.
return new ScopedModel<CounterModel>(
model: new CounterModel(),
child: new Column(children: [
// Create a ScopedModelDescendant. This widget will get the
// CounterModel from the nearest ScopedModel<CounterModel>.
// It will hand that model to our builder method, and rebuild
// any time the CounterModel changes (i.e. after we
// `notifyListeners` in the Model).
new ScopedModelDescendant<CounterModel>(
builder: (context, child, model) => new Text('${model.counter}'),
),
new Text("Another widget that doesn't depend on the CounterModel")
])
);
}
}
如何查找Model
ScopedModel
提供了两种方式:
- 使用
ScopedModelDescendant
Widget。 它将会找到Model
并且 会在Model
通知者通知变化时运行 builder函数。 - 使用
ScopedModel.of
静态方法。为了让这个方法更加易读和更频繁的方便访问,你可以考虑给你的Model
实现你自己的of
。
class CounterModel extends Model {
// ...
/// Wraps [ScopedModel.of] for this [Model].
static CounterModel of(BuildContext context) =>
ScopedModel.of<CounterModel>(context);
}
监听多个model
很多时候我们不是使用一个巨无霸AppModel
类来管理所有数据,而是会根据他们的业务逻辑进行拆分,比如 UserModel
、SearchModel
以及
ProductModel
。
但是,如果你需要从两个以上model获得数据,你需要思考如何获取。有两个选择:
- 使用多个
ScopedModelDescendant
Widgets. - 多次调用
ScopedModel.of
。无需取管理订阅关系,Flutter会通过InheritedWidgets
来考虑这些。
class CombinedWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final username =
ScopedModel.of<UserModel>(context, rebuildOnChange: true).username;
final counter =
ScopedModel.of<CounterModel>(context, rebuildOnChange: true).counter;
return Text('$username tapped the button $counter times');
}
}
demo 代码也可以参见 FlutterLearnNote ScopeModel分支.
以上就是关于scoped_model的介绍,今天的烂笔头就记到这里了。
如果你觉得这篇文章对你有益,还请帮忙转发和点赞,万分感谢。

您的关注将是我坚持的动力源泉,再次感谢。
网友评论