Android模块化实现

简单性和模块化是软件工程的基石;分布式和容错性是互联网的生命。 《Tim Berners-Lee》

什么是模块化

个人认为模块化是对整个项目的解耦以及项目维护带来极大的优势。而且在协同开发的导致各种各样的问题(例如文件冲突等问题)

模块化还可以实现模块内自管理,模块内你可以自由发挥你的管理方式,不管你是mvp,mvvm。每个人维护若干个模块。

基本思路

之前有阅读微信 Android 模块化架构重构实践,其中提出的pin工程让我眼前一亮,原来还可以这么搞。同时也参考了一下饿了么移动App的架构演进,那么其中的Excalibur系统也是一大亮点。

结合各大厂的架构演进,再加上即将要开展的新项目的情况,最后决定使用接口+SDK方式,进行模块化管理。

为什么不用类似微信的pin工程,原因是如果是要对现有的项目实现模块化,那么pin是一个非常好的过度方案,你无需进行繁杂的模块管理,直接在现有的工程上,以最快最少的方式就可以实现pin工程,最后完成module的转变。但如果我是全新的项目,则接口+模块会是更好的选择。

基本架构图

module

  • 最底层是Common: 里面主要是核心模块、公共UI模块以及第三方库
  • apis: 这里存放所有模块的暴露出来的接口
  • Bridge: 桥接器,里面可以按需进行模块的注册
  • App: App只依赖Bridge和Apis,模块的实现并不引用。

这样下来,就可以根据需要输出不同的App,特别像那种会进行更换厂商提供的sdk的,或者要求输出不同模块需要单独变成一个App的,简直是天大的福音。

项目结构

-w276

首先,我们假设要集成某厂商的摄像头。我们定义一个plugin_camera模块,里面是摄像头具体实现,里面只有一个简单的方法echo

1
2
3
4
5
6
public class Camera implements ICamera {
@Override
public void echo() {
Log.i("Camera","echo hello");
}
}

同时在Apis里面定义好要暴露的echo方法

1
2
3
public interface ICamera {
void echo();
}

然后桥接器里面进行模块的桥接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class Bridge {

private static final Bridge ourInstance = new Bridge();

public static Bridge getInstance() {
return ourInstance;
}

HashMap<Class, Class> build;

private Bridge() {
build = new HashMap<Class, Class>();
// register(ICamera.class, Camera.class);
register(ICamera.class, "com.rinfon.plugin_camera.Camera");
}

public Bridge register(Class interfaceClass, Class apiClass) {
build.put(interfaceClass, apiClass);
return this;
}

public Bridge register(Class interfaceClass, String apiClassName) {
try {
Class t = Class.forName(apiClassName);
build.put(interfaceClass, t);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return this;
}


public <T> T plugin(Class<T> type) {
try {
return (T) build.get(type).newInstance();
} catch (Exception e) {
e.printStackTrace();
}

return null;
}
}

最后在主app里面直接使用

1
2
Bridge bridge = Bridge.getInstance();
bridge.plugin(ICamera.class).echo();

如果某天产品经理跟你说,需要把Camera单独出来做成一个App,你只需要在plugin_camera模块里面增加对应的mainactivity和对应的Manifest.xml就可以了。

注意事项

  • 上面没有详细说明怎么实现模块App,但原理也很简单,新建模块的时候,你需要把模块内的build.gradle修改成
1
2
3
4
5
if (!isOpenCamera.toBoolean()) {
apply plugin: 'com.android.application'
} else {
apply plugin: 'com.android.library'
}

继续在模块内生成一个debug用的Manifest.xml和release用的Manifest.xml

然后在根目录下的gradle.properties里面增加以下内容

1
isOpenCamera=false

实现具体请看源码吧。

  • Bridge和Apis其实可以合并成一个模块也是可以的。
  • Bridge里面的模块注册使用的方式是反射,但这只是为了演示作用,其实如果真的在实际开发过程中,会使用模块自动注册的方式,而且像Demo里面直接反射。如果还用了ARoute的话,那么其中也包含了自动注册。但个人更加倾向的是使用gradle插件,通过操作字节码的方式来实现自动注册的。当然也可以使用AOP的方式来注册。后期会详细说说这几种方式的却别。

用一句网上看到的话来进行总结吧,我觉得非常好笑,也觉得非常的有道理的一句话。

任何软件工程遇到的问题都可以通过增加一个中间层来解决!

项目已上传github

-------------本文结束感谢您的阅读-------------
您的支持将是我最大的动力