【源码篇】Flutter GetX深度剖析 | 我们终将走出自己的路(万字图文) (3)

但是,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依赖注入-前

引入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相同的数据,传入的数据将不会被存储

也就是说相同类实例的对象,传入并不会被覆盖,只会存储第一条数据,后续被放弃

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgyyyj.html