我们很多人都知道 ARouter
, 也会优先选择 ARouter
, 这篇文章将会阐述为什么你需要选择 Component
, 而不是其他的.
大部分人选择 ARouter
是因为没有其他很好的评判标准, 觉得它 star
多就觉得可以信赖, 所以大部分人都是跟风的去使用 ARouter
, 难道除了 star
就没有其他很好的评判标准了吗?
如标题, 你得先明白你对项目实施组件化到底是想解决什么问题, 而不是盲目的.首先你一定是想解决最核心、最基础的两点:
有些框架可能把 Activity
路由跳转功能纳入 跨模块的功能调用 模块中, 也就是不直接提供路由的功能, 其实跨模块调用实现了, 你就可以自己实现 Activity
路由跳转
每一个框架都必须至少帮助开发者解决了跨模块的功能调用的这个问题, 这是一个框架的最最基础的.
组件化解决核心问题就够了吗
组件化解决核心问题了之后, 确实就可以着手组件化了, 但是组件化框架其实还可以提供更多, 去解决用户的痛点. 这在以前是基本上实现不了的!
WMRouter
和 Component
框架是有这个设计的)Retrofit
的接口调用(可以统一某些跳转, 提供统一的方法, 而不是到处复制, 便于维护)ActivityResult
(一个超级好用并且实用的功能)Intent
RxJava2
很多人可能对以上的很多点都没有很好的体会, 这里且让我慢慢说.
这点我就不说了, 在很多场景这个功能是需要的, 因为跳转失败在以往原生写法是体现为奔溃, 而框架会收集错误并且统一处理的, 但是很多时候我们想跳转失败后希望跳转到一个特殊的页面去, 给用户一个友好的展示! 这就是降级的功能, 不是很必须, 但是有用.
为什么说这个功能是超级好用并且神奇的一个功能, 下面我举几个例子:
上面这些例子只是比较典型的一个例子, 这类的情况很多, 我不会全部举例出来, 但是他们有一个共同点, 那就是进入某一个界面之前需要做一个 预处理
, 如果 预处理
失败了那么就不能够进入.
以往我们的写法无法两种
Activity
Activity
里面, 当完成预处理, 展示对应错误 UI 或者销毁界面这两种写法都会很恶心
第一种写法会让每一个跳转发起的地方都写一样的 预处理
代码, 不写又不行, 写了又恶心
第二种写法维护性是大大增强了, 因为代码在目标界面只写了一份, 但是这有一个很恶心的问题就是, 目标界面已经启动了, 当预处理失败之后, 对用户而言就会看到界面出来了又销毁了或者展示了一个错误视图, 展示错误视图这种已经是很好的处理了, 起码用户看的还挺舒服, 但是我们代码依旧写的很恶心
基于以上的, 页面拦截器应运而生, 目标就是解决此问题的
页面拦截器本质上是一个拦截器, 但是它不是一个全局拦截器, 当一个路由跳转到目标界面 A 之前, 框架会取出和 A 有关的拦截器, 并且执行这些拦截器, 执行成功才会跳转到目标界面.
这种方式就可以很好的解决上面我们的问题, 既不用在路由发起的地方去写这些 预处理
的代码, 也不用在目标界面里面去处理.
你可以为 A 目标界面声明一个页面拦截器, 预处理
代码就放在这里面. 完美的解决上述的问题!!
预处理
可以做任何的事情, 所以扩展性很强. 这是一个不可或缺的功能!!!
全局拦截器就不说了, 每一个框架都有, 就是那种每一个路由跳转都能拦截到的拦截器
路由接口是什么?它是一种可以允许用户用 类似 Retrofit
的接口调用, 完成一个路由跳转!
如下声明一个接口, 你可以描述一个方法为一个路由跳转, 然后你可以 如下方式调用
@RouterApiAnno()
public interface AppApi {
@HostAnno("help")
@PathAnno("testWeb")
void goToTestWebRouter();
}
// 跳转
Router.withApi(AppApi.class).goToTestWebRouter();
这种方式有啥用呢? 因为有些界面的参数比较复杂, 可能有十几个, 你会发现你每次都写下面这么长一段跳转是很恶心的一件事, 所以框架允许你可以先把跳转用接口的方法给描述出来, 这样每个地方调用就只要调用方法传入参数就行了, 不需要关心 key
的问题! 这个功能不是非常必须, 但是十分有用!
Router
.with(this)
.host("app")
.path("test")
.putString("name","cxj")
.putString("pass","123")
.putString("phone","158xxxxxxx")
.putString("desc","ccccccc")
......
......
......
.navigate();
为什么这点这么重要?因为我们写应用的时候, 几乎 95% 的代码都是在主线程上的, 我们很少写的代码在子线程上去运行!如果一个拦截器是需要弹框或者操作 UI 的, 那么 ARouter
之类的框架就会难受至极, 它只能在拦截器中去切换线程去做这件事, 其实设计上稍微变换一下, 采用 Callback
的形式就可以实现拦截器方法执行在主线程, 但是路由整体是可以 异步的
目前就发现可能用户会用到的两个地方!
而很多人觉得路由跳转整体不是异步的吗?那拦截器的实现方法怎么可能在主线程执行. 类似于 OkHttp
的拦截器实现当然不行, 这个和拦截器的方法实现有关, 有兴趣的可以查看 Component 的拦截器实现
ActivityResult
(贼好用!!!)我想这个功能就不用我说了把, 太重要了. 我说下以往的痛点吧! 以下情况都是会让开发者抓狂并且不得不做的事情
Adapter
中发现需要跳转界面拿 ActivityResult
Dialog
中发现需要跳转界面拿 ActivityResult
ActivityResult
Activity
上但是持有 Activity
的 Context
的地方发现需要跳转界面拿 ActivityResult
你在以上地方跳转了, 但是你需要在 Activity
中拿到 拿到 ActivityResult
, 这件事简直就是恶心, 因为它完全让我的代码分隔两地, 并且原本不需要 Activity
做处理却因为 Android
的这个设计而不得不这么做.
这个功能就是来完全解放你的, 它可以让你在任何持有 Activity Context 的地方都可以跳转直接在回调中拿到 ActivityResult, 而不需要中断你的代码, 并且不需要在 Activity 中写任何代码!
Intent
这个属于一个扩展功能, 但是也非常有用!
RxJava2
RxJava2
的火热程度不用我介绍了, 框架支持你扩展一个跳转是一个 [Observable], 在 wiki 中, 路由接口的方式使用下, 你可以让返回值是 [Observable]
Intent
ActivityResult
ActivityResult
的 resultCode
比如下面的使用, 更多的用法请参照 源码中的例子
@RouterApiAnno()
@HostAnno(ModuleConfig.App.NAME)
public interface AppApi {
@PathAnno("testQuality")
Completable goToTestQuality();
@RequestCodeAnno()
@NavigateAnno(forResult = true)
@PathAnno("testGetActivityResult")
Single<ActivityResult> testGetActivityResult();
}
请相信 Component 能带给你不一样的体验!
所有功能都是源自公司 App 组件化过程中遇到的痛点. 相信能给大家一个更好的组件化方案.