官方早期也提供的一种状态管理模式叫做BLOC。这种方式依赖于第三方包rxDart,以流(Stream)的方式很好地解决了setState()的问题。但是这种学习难度较大,对Flutter的新手并不友好。后来出现了一种第三方库Provider,这是一种先进的状态管理和依赖注入的工具,并且易于学习和理解,所以目前官方也推荐首选Provider。
本文我们也是主要介绍如何使用Provider来实现MVVM模式。
其中定义的baseModel 实现 ChangeNotifier 实时对数据进行更新后通知 ,里面存放数据请求时,界面如何展示,请求结束后 界面如何提示等 类似于 dialog的展示和销毁,还有实现notifyListeners 判断界面是否销毁,数据是否刷新
其中的定义的BaseView
import 'package:flutter/material.dart';
import 'package:flutter_provider_mvvm/viewmodels/base_model.dart';
import 'package:provider/provider.dart';
//baseview 就是一个组件weight
class BaseView<T extends BaseModel> extends StatefulWidget {
final Widget Function(BuildContext context, T model, Widget child) builder;
final T model;
final Widget child;
final Function(T) onModelReady;
BaseView({Key key, this.model, this.builder, this.child, this.onModelReady}) : super(key: key);
@override
_BaseViewState<T> createState() => _BaseViewState<T>();
}
class _BaseViewState<T extends BaseModel> extends State<BaseView<T>> {
T model;
@override
void initState() {
//方便初始化 一些操作,类似于刚进页面需要网络请求等
// 为什么这里我们需要使用StatefulWidget呢?因为我们需要在initState()在所有的子类中给出初始化的机会。
// 在所有需要应用MVVM模式的Widget都可以继承这个基类,传入ChangeNotifierProvider所需要的参数,其中包括viewModel,builder,child,还有初始化时的回调方法onModelReady()。
model = widget.model;
if (widget.onModelReady != null) {
widget.onModelReady(model);
}
super.initState();
}
//ChangeNotifierProvider<T extends ChangeNotifier> 实时通知
//通过Consumer 内部结构 进行接收
/**
* class Consumer<T> extends SingleChildStatelessWidget {
/// {@template provider.consumer.constructor}
/// Consumes a [Provider<T>]
/// {@endtemplate}
Consumer({
Key key,
@required this.builder,
Widget child,
}) : assert(builder != null),
super(key: key, child: child);
/// {@template provider.consumer.builder}
/// Build a widget tree based on the value from a [Provider<T>].
///
/// Must not be `null`.
/// {@endtemplate}
final Widget Function(BuildContext context, T value, Widget child) builder;
@override
Widget buildWithChild(BuildContext context, Widget child) {
return builder(
context,
Provider.of<T>(context),
child,
);
}
}
*/
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<T>(
child: Consumer<T>(
builder: widget.builder,
child: widget.child,
),
create: (BuildContext context) {
return model;
},
);
}
}