Flutter之GetX依赖注入Bindings使用详解
作用
Bindings 主要配合 GetX 路由和依赖一起使用,作用是在路由跳转页面加载时注入当前页面所需的依赖关系。Bindings 的好处是能统一管理页面的依赖关系,当业务复杂时可能一个页面需要注入大量的依赖,此时使用 Bindings 能更方便的维护页面的依赖关系。
使用
前面说了 Bindings 需要结合 GetX 路由一起使用,而 GetX 路由分为普通路由
和别名路由
,接下来分别看看如何使用。
首选创建一个自定义 Bindings 继承自 Bindings,比如计数器界面,创建一个 CounterBindings 在 dependencies
方法中注入 CounterController, 代码如下:
class CounterBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => CounterController());
}
}
上面通过 lazyPut
懒加载方式注入的,也可以使用前面讲到的其他注入方式注入。
普通路由
普通路由使用 Bindings 很简单,在路由跳转时加上 binding 参数传入创建的自定义 Bindings 对象即可:
Get.to(CounterPage(), binding: CounterBinding());
Get.off(CounterPage(), binding: CounterBinding());
Get.offAll(CounterPage(), binding: CounterBinding());
这样通过路由进入 CounterPage 时就会自动调用 CounterBinding 的 dependencies
方法初始化注入对应的依赖,在 CounterPage 中就能正常使用 Get.find
获取到注入的 CounterController 对象。
别名路由
Flutter应用框架搭建(一)GetX集成及使用详解 一文中介绍了别名路由的使用,需要先创建 GetPage
确定别名与页面的关系并配置到 GetMaterialApp
的 getPages
中,使用时通过 Get.toNamed
进行路由跳转,而 Get.toNamed
方法并没有 binding 参数用于传入 Bindings。
使用别名路由时需要在创建 GetPage
时就传入 Bindings 对象,如下:
GetPage(name: "/counter", page: () => CounterPage(), binding: CounterBinding());
跳转时正常使用 Get.toNamed
就能达到同样的效果。
Get.toNamed("/counter");
别名路由与普通路由对于 Bindings 的使用上还有一个区别,普通路由只有一个 binding 参数,只能传入一个 Bindings 对象,而别名路由除了 binding 参数以外还有一个 bindings 参数,可传入 Bindings 数组。使用如下:
GetPage(
name: "/counter",
page: () => CounterPage(),
binding: CounterBinding(),
bindings: [PageABinding(), PageBBinding(), PageCBinding()]);
那 bindings 的作用是什么呢?为什么需要传入一个数组?
通常一个页面只需要一个 Bindings 用来管理页面的依赖,但是当使用到 ViewPager 等嵌套组件或者存在页面嵌套时,因为页面中嵌套的页面不是通过路由加载出来的所以无法自动调用 Bindings 的 dependencies
方法来初始化依赖关系,而嵌套的页面有可能也需要单独显示,为了提高页面的复用性也会为嵌套页面创建 Bindings ,这样当页面嵌套使用时就可以把嵌套页面的 Bindings 传入到主页面路由的 bindings 中,使用如下:
/// ViewPager 页面路由
GetPage(
name: "/viewpager",
page: () => ViewPagerPage(),
binding: ViewPagerBinding(),
bindings: [PageABinding(), PageBBinding(), PageCBinding()]);
/// 单独 PageA pageB pageC 路由
GetPage(
name: "/pageA",
page: () => PageAPage(),
binding: PageABinding(),);
GetPage(
name: "/pageB",
page: () => PageBPage(),
binding: PageBBinding(),);
GetPage(
name: "/pageC",
page: () => PageCPage(),
binding: PageCBinding(),);
/// 使用
Get.toNamed("/viewpager");
Get.toNamed("/pageA");
Get.toNamed("/pageB");
Get.toNamed("/pageC");
这样就能实现,当在 ViewPager 中使用时也能初始化 ViewPager 中嵌套页面的依赖,单独使用某个 Page 时也能正常加载依赖。
原理
前面讲了 Bindings 的作用和使用方法,下面通过源码简单分析一下 Bindings 的原理。
Bindings 是一个抽象类,只有一个 dependencies
抽象方法,源码如下:
abstract class Bindings {
void dependencies();
}
在页面路由中注册 Bindings 后,页面初始化时会调用 Bindings 的 dependencies 方法,初始化页面依赖,其调用是在 GetPageRoute
的 buildContent
中,而 GetPageRoute
是继承至 Flutter 的 PageRoute
即在路由跳转加载页面内容时调用, 核心源码如下:
Widget _getChild() {
if (_child != null) return _child!;
final middlewareRunner = MiddlewareRunner(middlewares);
/// 获取 Bindings
final localbindings = [
if (bindings != null) ...bindings!,
if (binding != null) ...[binding!]
];
/// 调用中间件的 onBindingsStart 方法
final bindingsToBind = middlewareRunner.runOnBindingsStart(localbindings);
/// 调用 Bindings 的 dependencies 方法
if (bindingsToBind != null) {
for (final binding in bindingsToBind) {
binding.dependencies();
}
}
final pageToBuild = middlewareRunner.runOnPageBuildStart(page)!;
_child = middlewareRunner.runOnPageBuilt(pageToBuild());
return _child!;
}
@override
Widget buildContent(BuildContext context) {
return _getChild();
}
源码核心代码就是在创建页面 Widget 时获取路由传入的 Bindings ,然后依次调用 Bindings 的 dependencies 方法。
其中:
/// 获取 Bindings
final localbindings = [
if (bindings != null) ...bindings!,
if (binding != null) ...[binding!]
];
/// 调用中间件的 onBindingsStart 方法
final bindingsToBind = middlewareRunner.runOnBindingsStart(localbindings);
/// 调用 Bindings 的 dependencies 方法
if (bindingsToBind != null) {
for (final binding in bindingsToBind) {
binding.dependencies();
}
}
就是将路由中传入的 bindings 和 binding 取出放入同一个数组。然后依次调用 dependencies
方法,其中 binding 就是路由或 GetPage
中传入的 binding 参数,而 bindings 就是使用别名路由时在 ``GetPage 中传入的 Bindings 数组。
总结
本文通过介绍在 GetX 依赖注入中 Bindings 的作用以及使用方法,再结合 GetX 的源码分析了 Bindings 的实现原理,更进一步了解了 Bindings 为什么能实现页面依赖注入的管理,希望通过源码让大家更好的理解 GetX 中的 Bindings ,从而在开发中灵活使用 Bindings 管理页面所需的依赖。
作者:loongwind
链接:https://juejin.cn/post/7062516045130498084
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。