但是,Element提供的获取InheritedElement的方式,终究和路由机制无法很好的结合;这也模块设计无法避免的事情,或许某些模块设计的最优解,很难顾忌到其它模快的一些机制
InheritedWidget这把神兵利器,在我们学习Flutter历程中给予了很多帮助
但是,当需求逐渐复杂,你的技术不断精进
屠龙刀这把神兵,或许渐渐的,不太适合你了
有时候,它甚至制约了你的出招
一位制造神兵的铁匠,在他心中,最好的神兵利器,或许永远是下一把
大部分的状态管理框架,将界面层和逻辑层分开,都是逻辑层来处理界面的刷新;逻辑层可以交给InheritedWidget存储管理;说明,我们自己也一定可以存储管理!
自己来管理逻辑层,可以摆脱Element树的约束,不用被困在Element树的父子节点中
在路由跳转的页面中,可以很轻松的获取上一页面,下一个页面或者上上一个页面逻辑层。
这也是GetX中一个核心思想,这并不是一个多么新颖或高深技术,但是,我这觉得这是一种思维上的突破,可以带来更多的可能
依赖注入 说明依赖注入有如下实现方式(维基百科):
基于接口。实现特定接口以供外部容器注入所依赖类型的对象。
基于 set 方法。实现特定属性的public set方法,来让外部容器调用传入所依赖类型的对象。
基于构造函数。实现特定参数的构造函数,在新建对象时传入所依赖类型的对象。
基于注解。基于Java的注解功能,在私有变量前加“@Autowired”等注解,不需要显式的定义以上三种代码,便可以让外部容器传入对应的对象。该方案相当于定义了public的set方法,但是因为没有真正的set方法,从而不会为了实现依赖注入导致暴露了不该暴露的接口(因为set方法只想让容器访问来注入而并不希望其他依赖此类的对象访问)。
强耦合类型的,基于构造函数
class Test { String msg; Test(String msg) { this.msg = msg; } }set方式
class Test { String? _msg; void setMsg(String msg) { this._msg = msg; } }如果在Java中,图一时方便,直接在构造函数里面传值,然后需要的值越来越多,导致需要增加该构造函数传参,因为强耦合很多类,一改构造函数,爆红一大片(Dart构造函数可选参数的特性,就没有这类问题了)
Getx注入的GetXController都是由GetX框架自己来维护的,如果没有GetX这个中间层会是什么样的?
引入GetX这个中间层来管理
看下图,瞬间就想到了中介者模式
这也是控制反转的思想(创建对象的控制权本来在自己手上,现在交给了第三方)
Put来看下GetX注入的操作
put使用
var controller = Get.put(XxxGetxController());看看内部操作
哎,各种骚操作
主要逻辑在Inst中,Inst是GetInterface的扩展类
class _GetImpl extends GetInterface {} final Get = _GetImpl(); extension Inst on GetInterface { S put<S>(S dependency, {String? tag, bool permanent = false, InstanceBuilderCallback<S>? builder}) => GetInstance().put<S>(dependency, tag: tag, permanent: permanent); }主要的逻辑看来还是GetInstance中
大家可以看看这地方单例的实现,我发现很多源码都用这种方式写的,非常简洁
全局的数据都是存在 _singl 中,这是个Map
key:对象的runtimeType或者类的Type + tag
value:_InstanceBuilderFactory类,我们传入dependedt对象会存入这个类中
_singl 这个map存值的时候,不是用的put,而是用的putIfAbsent
如果map中有key和传入key相同的数据,传入的数据将不会被存储
也就是说相同类实例的对象,传入并不会被覆盖,只会存储第一条数据,后续被放弃