一背景
还记得上一次分享的模块间通信和调用吗? Android 模块化之路 模块间通信 在这个文章里面, 我们说到, 如果涉及到跨进程, 那我们可以用 AIDL 的方式来解决跨进程的问题
但用户的一些质疑声也来了:
我还是一个小 App, 不用跨进程, 我不是淘宝, 不是微信, 用 AIDL 太重了点吧?
AIDL 只支持基本类型的入参和出参, 并且还是有点学习成本的, 有没有简单一 点的方案呢? 就是那种一点就透, 一用就爽, 一爽就开心的奇淫技巧?
好吧, 那就再介绍另外一种模块间通信的方式
二迷你模块间调用
和前面提到的 AIDL 的方式一样, 也是通过面向接口编程, 子模块增加接口层, 然后具体的实现不再通过 AIDL 来实现, 而是通过最简单粗暴的 Class.forName();
在 web 端开发, Spring 定义出 Service 和 ServiceImpl, 通过 XML 文件定义 bean 的实现
我们在这里也采用同样的方式
首页我们祭出我们的基类:
定义接口基类
上面的是一个接口类, 所有模块接口声明都继续此接口
比如我们定义 IShopcartService 接口代码如下:
购物车接口声明
可以看到上面就是最普通的 JAVA 写法, 解决了 AIDL 的出参和入参要实现序列化麻烦的问题
我们再来看一下具体的实现:
购物车接口的具体实现
然后就是怎么获取这个 Service 的实例了, 调用代码如下:
购物车服务获取
那 Services 中的代码又是如何实现的呢?
原来是通过一个 Map 来维护的接口名和实现的映射关系, 还加了个 LRU 缓存
讲到这里, 基本这个小巧的设计实现和思路就完成了
但还有两个问题需要解决:
实例什么时候初始化? App 启动时就直接实例化好还是用到的时候再 newInstance 呢? 上面的实现是放到用到的时候再初始化
实例的映射关系存到哪里? 放到 asset 里面, 还是自己读 xml 文件, 还是放到 raw 里面, 弄一个 properties 文件呢? 我这里的实现是读 RAW, 大家可以自行改造
raw 的配置文件
源码地址: https://github.com/ssevening/AndroidAidlExample
三再说进阶
看到上面的内容, 然后肯定又要说了, 擦, 就这么简单? 一点逼格也没有啊? 怎么样增加一点逼格呢? 这里给大家抛几个问题, 也是几个方向, 完成了这几个问题后, 你的逼格也就上去了
要自己来维护接口和实现类的映射, 有点 Low, 考虑机器自动生成吧, 那就是去看看运行时注解
写在 raw 中的文件, 一是多模块化的话, 只有在主工程中定义这个 RAW 文件, 有没有办法放到子模块中定义呢?
怎么样解决规则文件的批写错误呢?
如果遇到获取服务失败, 有没有及时发现和报警的功能?
有没有能力做到 ABTest 动态替换呢? 比如新发布一个实现类, 让新类和旧类同时运行, 但又可以在线上动态替换?
Service 中怎样进行一些环境变量的区分或 mock 呢? 比如 DEBUG 环境下打印日志?
大家多想一想, 然后把上面的问题解决了, 一个高逼格的 模块间调用框架就出来了
最后, 提醒一下, 上线前的混淆不要忘记 keep 所有 extends IJavaService 的类噢
四一些总结
模块间通信扯到这里, 基本上分为三个阶段:
创业型 App, 自建 Map 来维护服务关系, 最简单, 也最稳定
搞一些高科技, 然后把运行时注解也搞上, 自动生成, 同时完成路由, 比如阿里的: ARouter 也是个不错的方案
要跨进程, 要跨应用调用, 这个时候, 就只有 AIDL 的方案了, 但有成本, 第一种自建 Map 的方式, 可以轻松切换到 AIDL 的方式, 而如果是 ARouter 的方式, 估计切到 AIDL 就不太好了当然, 如果都要用到 AIDL 的时候, 创业必然成功, 团队必然壮大! 也不在乎重构一把了!
继续关注, 接着扯 Android 模块化过程中, 还有哪些问题需要解决和面对
作者: 辰星某知名公司技术专家 文章转载自: Android 那些事
来源: http://mp.weixin.qq.com/s/uYtQtQSQHY2_AFiyqg_Ltg