为什么需要组件化?

组件化顾名思义就是将代码按功能或者业务划分成一个个组件,小的项目一般不需要,只有当项目大到一定程度,代码量足够多的时候我们就需要用到组件化。组件化总体来说有下面几个收益点:

  • 代码隔离:不同的功能收敛到不同的组件里,对一个功能(组件)的修改不会影响到另一个组件,减少开发中误伤别人或者被别人误伤的概率
  • 提高开发效率:隔离开来,每个组件可以单独运行调试,不至于你的一个bug影响我几天
  • 提高协作效率:代码划分清晰,人员自然也可以清晰划分,每个组件有对应的owner,没有三不管地带;每个组件只暴露自己需要对外暴露的方法,其他组件不需理解该组件的具体实现,需要就调用就好
  • 可复用性:对于一些通用的功能抽象成一个组件,便于复用

怎样组件化?

将不同功能的代码收敛到各自独立的module,做好代码隔离,A业务不能直接引用到B业务module里的代码,也就限制了B的改动会对A造成的影响。module之间的依赖关系分层级,顶层依赖底层,底层不能依赖顶层,这样可以让顶层的改动影响限制在自己module,其他顶层module因为没有引用到改动的module所以不会受影响。

android 怎么组件化开发 android组件化原理_组件化

 

如图,不同的组件已经划分成不同的module,代码层面已经完全隔离开了,就是说组件A不能直接引用到组件B,这时候,如果A要用到B的能力,要么让整个组件A依赖组件B,implementation project(':B'),但是如果B又要用到A的能力,又依赖A,继续implementation project(':A'),那这两个组件互相依赖,A的改动会影响到B,B的改动也会影响A,跟我们原来的预期背道而驰。所以我们需要一个通信框架,组件只暴露必要的方法供其他组件调用,且组件间不能互相依赖。

A功能拆成两个组件,A-api表示A组件对外暴露的能力,这里只写接口;A-impl作为A组件能力的实现,代码逻辑写在这里;实现一个base组件,impl层依赖base层,base层依赖api层,base里面通过反射创建和缓存impl的实例,存储一个servicemap,key为接口,value为对应反射创建的impl(service实例),其他的B、C组件同理,这样A,B,C等组件不会互相依赖,但都可以通过依赖base,通过接口方法调用到对应的组件能力。比如A要用到B的能力,可以拿到B-api的接口,到base层取对应的实例,base层通过反射创建B-impl里对接口的实现并缓存起来,返回给A,这样,A就可以调用到B-api里暴露的方法。

中转组件base和反射创建是去除双向依赖的关键。

可以看到,只要维护好各个组件间的依赖关系,可以做到,对顶层组件的修改不会影响到其他组件,对底层组件的修改只影响依赖它的组件。

代码划分清晰,人员协作清晰,这就是组件化带来的效果。

Q&&A

组件化后如何独立调试?

独立调试本质上就是你的组件不再是一个library,而是一个application。

想要灵活切换可以在gradle.properties配置变量,build.gradle判断变量去执行不同逻辑

核心改动点:

  • 切换library为application:在build.gradle修改apply plugin: 'com.android.library'为apply plugin: 'com.android.application',可判断变量动态切换
  • 配置入口activity:application是需要入口activity的,需要在AndroidManifest.xml配置好,可判断变量再根据sourceset指定不同的AndroidManifest.xml
  • 配置application信息:因为已经作为一个application了,需要配置android{}块里的applicationId、compileSdkVersion等

sync后你会发现你的组件已经被Android studio识别为app了,选择后点击运行即可