Android Route 路由解析 - tenji/ks GitHub Wiki
Android Route 路由解析
随着项目的开发,业务不断壮大,业务模块越来越多,各个模块间相互引用,耦合越来越严重,同时有些项目可能还需要独立对外输出,所以模块解耦,组件化变得尤为紧迫。
一、泛化路由简介
泛化模块路由,支持在各种 SDK 产品中使用(源码拷贝更新 applicationId 即可,内部可自由增加订制化内容) (本项目基于 ModularizationArchitecture,在其基础上进行了精简):
- 去掉了同步异步调用 Router 只负责做好解耦和转发工作,剩余的线程切换、同步异步看业务需要,在分发到业务之后,由具体业务操作线程同步异步;
- 去掉了跨进程组件;
- 作为通用 SDK 内部嵌入的 Router 较少用到跨进程,如果需要在主进程分发处做进程切换 此模块只有 Jar 包,不用在 manifest 声明任何组件,直接使用即可,无任何依赖。
- 一切目标为了精简,适合 SDK 产品使用;
- 反射动态拼装组件,像乐高积木一样任意组合输出子模块;
- 模块测试、编译更加简单高效。
二、路由方案演进
2.1 阶段一(原始社会)
如上图所示,早期代码没有任何细分,所有代码都在一个模块,模块直接直接依赖。
2.2 阶段二(奴隶社会)
伴随着模块业务功能的分工,不同的模块被拆分开来,但是随着业务直接互相调用,逐渐发展为如下阶段。
2.3 阶段三(封建社会)
各个模块直接依赖错综复杂,扩展和维护性大打折扣,于是爆发了现代革命。
2.4 阶段四(资本主义社会)
不同模块完全隔离,通过公共的 Router 模块进行通信,各个模块自由扩展,维护性大大提高。
模块可以动态拆解,按需打包使用,如下图:
更进化一步,将公共库抽离到 Router,模块复用度进一步提高。
后续多进程方案暂时不在本文讨论之列,因为可以在自己的模块完成多进程,不一定非要用 Router 操作多进程,减少 Router 的责任。
一次 Router 的调用时序如下:
三、使用方式
- App:可运行的 APP Module;
- Library Moudule:模块化中的单一业务或功能组件;
- Action:跨模块调用的具体实现;
- ActionResult:Action 调用后返回的结果;
- Provider:Action 簇,将一组 Action 放到一起,便于注册;
- RouterRequest:调用 Action 时的请求信息;
- RouterResponse:Action 调用完成之后的响应信息;
- LocalRouter:单进程本地局域路由器
3.1 在 Application oncreate 中初始化 Router
// 注册 Router
RouterManager.getInstance().registerApplicationLogic(MainApplicationLogic.class);
RouterManager.getInstance().registerApplicationLogic(WebApplicationLogic.class);
RouterManager.getInstance().registerApplicationLogic(MusicApplicationLogic.class);
RouterManager.getInstance().registerApplicationLogic(PicApplicationLogic.class);
// 初始化 Router
RouterManager.getInstance().init(this);
3.2 创建自定义 ApplicationLogic
public class CustomApplicationLogic extends BaseApplicationLogic {
@Override
public void onCreate() {
// 注册 Provider,详见 2.4
LocalRouter.getInstance(mApplication).registerProvider("util", new UtilProvider());
}
}
3.3 创建 Provider
public class UtilProvider extends MaProvider {
@Override
protected void registerActions() {
registerAction("md5",new MD5EncryptAction());
}
}
3.4 实现 Action
public class PlayAction implements RouterAction {
@Override
public void invoke(Context context, HashMap requestData, RouterCallback callback) {
Intent intent = new Intent(context, MusicService.class);
intent.putExtra("command", "play");
context.startService(intent);
if (callback != null) {
HashMap result = new HashMap();
result.put(RouterCallback.KEY_VALUE,"play success");
callback.onResult(RouterCallback.CODE_SUCCESS,result);
}
}
}
3.5 调用
RouterManager.getInstance().route(context, routerRequestBuilder);