闽公网安备 35020302035485号
为了支持使用静态的 ViewModel.update 方法来更新模型,我们需要引入额外一个额外的有状态组件。这会稍微有点复杂。
1.将 ModelBinding 变成了一个有状态组件,并且持有当前状态模型对象。
2.为ModelBinding 构建了一个_ModelBindingScope 的 InheritedWidget 子组件,该子组件引用了 State<ModelBinding>——即_ModelBingingState,其实就相当于是引用了父级的状态。
3.为了改变 ModelBinding 当前模型的值,从而在调用 setState 方法重建 ModelBinding,并重建下级的_ModelBindingScope。
4.通过_ModelBindingScope 来实现ViewModel类的静态获取模型对象及更新对象
static ViewModel of(BuildContext context) {
_ModelBindingScope scope =
context.dependOnInheritedWidgetOfExactType(aspect: _ModelBindingScope);
return scope.modelBindingState.currentModel;
}
static void update(BuildContext context, ViewModel newModel) {
_ModelBindingScope scope =
context.dependOnInheritedWidgetOfExactType(aspect: _ModelBindingScope);
scope.modelBindingState.updateModel(newModel);
}
现在,任何 ModelBinding 的子组件都可以使用这些方法来更新模型数据了,下面的按钮代码就同时获取和更新了模型的数据。Widget build(BuildContext context) {
return ElevatedButton(
child: Text('Hello World ${ViewModel.of(context).value}'),
onPressed: () {
ViewModel model = ViewModel.of(context);
ViewModel.update(context, ViewModel(value: model.value + 1));
},
);
}
运行一下,一切正常(完整代码:model_binding_v1.dart),是不是该庆祝一下?然而,如果我们有技术上百个状态的话我们要写几十上百个 ModelBinding 类,而且每个 Model 都要提供一个静态的 of(context)和 update 方法?class _ModelBindingScope<T> extends InheritedWidget {
_ModelBindingScope({
Key key,
@required this.modelBindingState,
Widget child,
}) : assert(modelBindingState != null),
super(key: key, child: child);
final _ModelBindingV2State<T> modelBindingState;
@override
bool updateShouldNotify(_ModelBindingScope oldWidget) => true;
}
改起来很简单,只需要加上泛型参数就好了。接下来是_ModelBindV2State,这个类也许改成泛型。class _ModelBindingV2State<T> extends State<ModelBindingV2<T>> {
T currentModel;
@override
void initState() {
super.initState();
currentModel = widget.create();
}
void updateModel(T newModel) {
if (currentModel != newModel) {
setState(() {
currentModel = newModel;
});
}
}
@override
Widget build(BuildContext context) {
return _ModelBindingScope<T>(
modelBindingState: this,
child: widget.child,
);
}
}
实际上,也只是增加了泛型参数,这里有个地方需要注意的是,之前我们是在_ModelBidingV2State 中直接构建初始状态了,现在由于是泛型,我们没法直接构建泛型对象,因此需要从有状态组件中获取。这里我们在 initState 中调用了 ModeBinding 类的 create 方法返回一个泛型对象(当然,也可以直接使用赋值,取决于 ModelBinding 类如何获取初始状态对象)。// 堆代码 duidaima.com
class ModelBindingV2<T> extends StatefulWidget {
ModelBindingV2({Key key, @required this.create, this.child})
: assert(create != null),
super(key: key);
final ValueGetter<T> create;
final Widget child;
@override
_ModelBindingV2State<T> createState() => _ModelBindingV2State<T>();
static T of<T>(BuildContext context) {
_ModelBindingScope<T> scope =
context.dependOnInheritedWidgetOfExactType(aspect: _ModelBindingScope);
return scope.modelBindingState.currentModel;
}
static void update<T>(BuildContext context, T newModel) {
_ModelBindingScope<T> scope =
context.dependOnInheritedWidgetOfExactType(aspect: _ModelBindingScope);
scope.modelBindingState.updateModel(newModel);
}
}
改造完成之后,我们的实际 Controller 的代码就变成下面这样了:class StateViewControllerV2 extends StatelessWidget {
StateViewControllerV2({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('模型绑定泛型版'),
),
body: Center(
child: ModelBindingV2(
create: () => ViewModel(),
child: ViewController(),
),
),
);
}
}
class ViewController extends StatelessWidget {
const ViewController({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return ElevatedButton(
child: Text('Hello World ${ModelBindingV2.of<ViewModel>(context).value}'),
onPressed: () {
ViewModel model = ModelBindingV2.of<ViewModel>(context);
ModelBindingV2.update(context, ViewModel(value: model.value + 1));
},
);
}
}
可以看到,整个 ModelBinding 类完成了状态的获取和更新,而且适用于任何状态模型类。