用了两年的flutter,有了一些心得,不虚头巴脑,只求实战有用,以供学习或使用flutter的小伙伴参考,学习尚浅,如有不正确的地方还望各路大神指正,以免误人子弟,在此拜谢~(原创不易,转发请标注来源和作者)
注意:无特殊说明,flutter版本为3.0+
上一篇分析了如何使用GetX组织项目结构,这一篇我们来探讨一下如何实现页面多例。
一.场景分析
我们在实现大部门业务的时候都是单例的,通俗来讲就是在页面跳转后,栈内不会出现两个相同的页面,在上一篇中使用Getx组织项目结构,我们处理一般页面的模式是在binding文件中使用lazyPut,绑定controller,lazyPut 是singleton单例模式的。
Get.lazyPut(() => MainController());
然后再view相关页面需要使用controller逻辑的时候
GetBuilder<MainController>(
id: "xxxx",
builder: (ctl) {
return Container();
})
这样就实现了基本的mvc模式。
二.多页面场景分析
举一个多页面场景的例子:比如说一个书架app,我们看一个流程:
我们可以看到从A书籍详情到B书籍详情,栈中出现了两次书籍详情,我们实现页面过程中逻辑都是一致的,只是参数不同(书籍id不同)。
如果依然使用lazyPut绑定controller的话,由于A书籍页面详情 已经初始化一次controller,那么B书籍详情调用的时候,只会拿到A书籍的数据,导致页面无法刷新,这就是controller单例导致的错误。那么我么探讨一下如何解决单页面多例的问题。
三。使用controller 的create实现多例
1.首先肯定要在bingding中放弃lazyPut 的形式,采用create
Get.create<MainController>(() => MainControllerController(),permanent: false);
2.取消GetBuilder的全局模式,将controller传值到GetBuilder中的init。
GetBuilder<MainController>(
id: "xxxx",
init: controller,
global: false,
builder: (ctl) {
return Container();
})
使用这样的模式,就可以简单实现了多例,麻烦的是,controller需要从主页传入到页面的各个组件中,如果页面组件比较多也是比较麻烦的(大部分页面的组件不会涉及过多)
四。使用tag模式实现多例
细心的同学可能在使用的时候会发现,lazyPut有可选参数tag
void lazyPut<S>(InstanceBuilderCallback<S> builder,
{String? tag, bool fenix = false}) {
GetInstance().lazyPut<S>(builder, tag: tag, fenix: fenix);
}
然后再Get.find方法中也有通过tag查找controller的方法。所以我们也有思路,比如上面的例子,在A书籍详情可以初始化tag为”A“的controller,待到B书籍详情的时候我们的tag为”B“。
不幸的是我们依然需要在GetBuilder中修改
GetBuilder<MainController>(
id: "xxxx",
tag: “A”
builder: (ctl) {
return Container();
})
综合考虑使用复杂度,使用controller的create模式相比tag模式更简单一些,也是我自己项目里一直在用的模式。