去年公司Flutter的项目采用的是类似Android 里面的MVP(Model View Persenter)模式,Model和View以及Persenter之间采用接口解耦,虽然采用插件来生成对应的基本模板,渐渐的发现接口过多,慢慢的就发现很多问题。
主要的问题是逻辑复杂的情况下,接口会比较多,而且Presenter也不太好复用(可能技术太菜了),之后引入Provider框架来解决页面局部刷新功能。
之后就想到MVVM框架,View和ViewModel可以采用Provider来做事件传递,做双向绑定
View: 主要是就是各类Widget Page页面
ViewModel: 主要是继承ChangeNotifier
Mode:主要是从网络/数据库/本地资源文件等
ViewModel ->Model 之间可以通过Future方式获取数据
ViewModel <-> View之间通过Provider来双向数据绑定,实时响应
由于Provider可以做到细粒度的局部刷新,一些公用的Widget可以做到组合使用,而对应的ViewModel的逻辑也可以很好的与Widget通过ChangeNotifier复用使用。
对应的是普通的StatefulWidget界面
由于需要绑定对应的ViewModel,需要在对应的模块中通过Provider引入
下面是普通的Provider的引入方法
Widget _authGestureWidget() {
return ChangeNotifierProvider<SecuritySettingsNotifier>.value(
value: _settingsNotifier,
child: Consumer<SecuritySettingsNotifier>(
builder: (context, settingsNotifier, _) {
return Container(
color: DHColor.colorFFFFFF,
margin: EdgeInsets.only(bottom: DHSize.dp(8)),
child: _settingsNotifier.canAuch
? DHListTileLine(
leadingText: "每次打开都需要验证身份",
isDivider: false,
trailing: DHSwitchButton(
value: _settingsNotifier.isAuthGesture,
activeColor: DHColor.color_B69E74,
onChanged: (bool isOpen) {
handleTapAuth();
}),
isTrailing: false,
)
: Container(),
);
},
));
}
对应的只是一个验证身份的模块,具体需要去了解一下Provider的用法
ViewModel 主要是展示对应的业务逻辑 下面展示一个比较普通的业务逻辑
class SecuritySettingsNotifier with ChangeNotifier {
///指纹密码
bool _isAuthPWD = false;
bool get isAuthGesture => _isAuthPWD;
set isAuthGesture(bool value) {
_isAuthPWD = value;
notifyListeners();
}
List<BiometricType> _availableBiometrics;
List<BiometricType> get availableBiometrics => _availableBiometrics;
///是否支持脸部识别
bool canFaceAuth = false;
///是否支持指纹
bool canTouchAuth = false;
///设备是否支持脸部、指纹识别
bool canAuch = false;
set availableBiometrics(List<BiometricType> value) {
_availableBiometrics = value;
if (_canAvailableBiometrics()) {
for (BiometricType type in _availableBiometrics) {
if (BiometricType.face == type) {
canFaceAuth = true;
} else if (BiometricType.fingerprint == type) {
canTouchAuth = true;
}
}
}
canAuch = (canFaceAuth || canTouchAuth);
notifyListeners();
}
bool _canAvailableBiometrics() {
return _availableBiometrics != null && _availableBiometrics.isNotEmpty;
}
}
主要用于控制设置页面的是否支持指纹识别相关的设置
此时的Model展示就和一般的获取数据类似
class MineInfoModel extends AbstractModel {
@override
void dispose() {
HttpManager().cancel(tag);
}
Future<MineInfoBean> getMineInfoDetail() {
return HttpManager().postAsync(
url: Api.getUserInfo,
jsonParse: (val) => MineInfoBean.fromJson(val),
tag: tag,
);
}
}
直接获取对应的数据即可
ViewModel 获取数据直接通过接口调用Model的对应方法即可,通过Future then等操作
View和ViewModel之间则是通过Provider联动,但是会存在一些提交数据的操作,就需要通过回调CallBack的操作来直接响应对应的数据结果
而对于列表类型的数据或者是获取数据的则可通过Provider的ChangeNotifier 局部刷新Widget来驱动界面的更新
具体后续会添加上对应的Demo展示