Android 模块化之路 模块间调用简易实现方案

一、背景

还记得上一次分享的模块间通信和调用吗?Android 模块化之路 模块间通信 在这个文章里面,我们说到,如果涉及到跨进程,那我们可以用 AIDL 的方式来解决跨进程的问题。

但用户的一些质疑声也来了:

  • 我还是一个小 App,不用跨进程,我不是淘宝,不是微信,用 AIDL 太重了点吧?
  • AIDL 只支持基本类型的入参和出参,并且还是有点学习成本的,有没有简单一 点的方案呢?就是那种一点就透,一用就爽,一爽就开心的奇淫技巧?

好吧,那就再介绍另外一种模块间通信的方式。

二、迷你模块间调用

和前面提到的 AIDL 的方式一样,也是通过面向接口编程,子模块增加接口层,然后具体的实现不再通过AIDL来实现,而是通过最简单粗暴的Class.forName();

在 WEB 端开发,Spring 定义出 Service和 ServiceImpl,通过 XML 文件定义bean的实现。

我们在这里也采用同样的方式。

首页我们祭出我们的基类:

定义接口基类

上面的是一个接口类,所有模块接口声明都继续此接口。

比如我们定义 IShopcartService 接口代码如下:

购物车接口声明

可以看到上面就是最普通的 JAVA 写法,解决了 AIDL 的出参和入参要实现序列化麻烦的问题。

我们再来看一下具体的实现:
购物车接口的具体实现

然后就是怎么获取这个Service的实例了,调用代码如下:

购物车服务获取

那 Services 中的代码又是如何实现的呢?

原来是通过一个 Map 来维护的接口名和实现的映射关系,还加了个 LRU 缓存

讲到这里,基本这个小巧的设计实现和思路就完成了。

但还有两个问题需要解决:

  1. 实例什么时候初始化? App 启动时就直接实例化好还是用到的时候再newInstance呢? 上面的实现是放到用到的时候再初始化。

  2. 实例的映射关系存到哪里? 放到asset里面,还是自己读 xml文件,还是放到raw里面,弄一个properties文件呢?我这里的实现是读 RAW,大家可以自行改造。
    raw的配置文件

源码地址:https://github.com/ssevening/AndroidAidlExample

三、我们再说进阶

看到上面的内容,然后肯定又要说了,擦,就这么简单?一点逼格也没有啊?怎么样增加一点逼格呢?这里给大家抛几个问题,也是几个方向,完成了这几个问题后,你的逼格也就上去了。

  • 要自己来维护接口和实现类的映射,有点 Low,考虑机器自动生成吧,那就是去看看运行时注解。
  • 写在raw中的文件,一是多模块化的话,只有在主工程中定义这个 RAW 文件,有没有办法放到子模块中定义呢?
  • 怎么样解决规则文件的批写错误呢?
  • 如果遇到获取服务失败,有没有及时发现和报警的功能?
  • 有没有能力做到 ABTest 动态替换呢?比如新发布一个实现类,让新类和旧类同时运行,但又可以在线上动态替换?
  • Service中怎样进行一些环境变量的区分或mock呢?比如 DEBUG 环境下打印日志?

大家多想一想,然后把上面的问题解决了,一个高逼格的 模块间调用框架就出来了。

最后,提醒一下,上线前的混淆不要忘记 keep 所有 extends IJavaService 的类噢。

四、一些总结

模块间通信扯到这里,基本上分为三个阶段:

  1. 创业型 App,自建 Map 来维护服务关系,最简单,也最稳定。
  2. 搞一些高科技,然后把运行时注解也搞上,自动生成,同时完成路由,比如阿里的:ARouter 也是个不错的方案。
  3. 要跨进程,要跨应用调用,这个时候,就只有 AIDL 的方案了,但有成本,第一种自建 Map 的方式,可以轻松切换到 AIDL 的方式,而如果是ARouter的方式,估计切到 AIDL 就不太好了。当然,如果都要用到 AIDL 的时候,创业必然成功,团队必然壮大!也不在乎重构一把了!

下一篇,接着扯Android 模块化过程中,还有哪些问题需要解决和面对。

赛文市场营销

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注