Android Router 路由框架解析
作者:国风
背景
随着项目的开发,业务不断壮大,业务模块越来越多,各个模块间相互引用,耦合越来越严重,同时有些项目可能还需要独立对外输出,所以模块解耦,组件化变得尤为紧迫。在写本文之前,已经有了较好的模块化组件化设计 Android 架构思考(模块化、多进程))。本文按照其思路对其进行介绍,然后在作者基础上,抽离了 core 逻辑,封装为简单的单进程 SDK 产品模块化框架,github 泛化路由
泛化路由简介
泛化模块路由,支持在各种SDK产品中使用(源码拷贝更新applicationId即可,内部可自由增加订制化内容) (本项目基于ModularizationArchitecture,在其基础上进行了精简):
- 去掉了同步异步调用 Router只负责做好解耦和转发工作,剩余的线程切换、同步异步看业务需要,在分发到业务之后,由具体业务操作线程同步异步。
- 去掉了跨进程组件
- 作为通用SDK内部嵌入的Router较少用到跨进程,如果需要在主进程分发处做进程切换 此模块只有Jar包,不用在manifet声明任何组件,直接使用即可,无任何依赖。
- 一切目标为了精简,适合SDK产品使用
- 反射动态拼装组件,像乐高积木一样任意组合输出子模块
- 模块测试、编译更加简单高校
路由方案演进
原始社会
如上图所示,早期代码没有任何细分,所有代码都在一个模块,模块直接直接依赖。
奴隶社会
伴随着模块业务功能的分工,不同的模块被拆分开来,但是随着业务直接互相调用,逐渐发展为如下阶段
封建社会
各个模块直接依赖错综复杂,扩展和维护性大打折扣,于是爆发了现代革命
资本主义社会
(为何不用社会主义,因为。。。。)
不同模块完全隔离,通过公共的 Router 模块进行通信,各个模块自由扩展,维护性大大提高。
模块可以动态拆解,按需打包使用,如下图
更进化一步,将公共库抽离到 Router,模块复用度进一步提高。
后续多进程方案暂时不在本文讨论之列,因为可以在自己的模块完成多进程,不一定非要用 Router 操作多进程,减少 Router 的责任。
一次 Router 的调用时序如下:
使用方式
- App:可运行的APP Module
- Library Moudule:模块化中的单一业务或功能组件
- Action:跨模块调用的具体实现
- ActionResult:Action调用后返回的结果
- Provider:Action簇,将一组Action放到一起,便于注册
- RouterRequest:调用Action时的请求信息
- RouterResponse:Action调用完成之后的响应信息
- LocalRouter:单进程本地局域路由器
1.在Application oncreate中初始化Router
1
2
3
4
5
6
7
// 注册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);
2. 创建自定义ApplicationLogic
1
2
3
4
5
6
7
public class CustomApplicationLogic extends BaseApplicationLogic {
@Override
public void onCreate() {
// 注册Provider,详见2.4
LocalRouter.getInstance(mApplication).registerProvider("util",new UtilProvider());
}
}
3. 创建Provider
1
2
3
4
5
6
public class UtilProvider extends MaProvider {
@Override
protected void registerActions() {
registerAction("md5",new MD5EncryptAction());
}
}
4.实现Action
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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);
}
}
}
5.调用
1
RouterManager.getInstance().route(context, routerRequestBuilder);
致谢: Spindy