Android组件化经验分享
最近由于项目需求,app A需要使用另一个app B的全部功能,即B要作为A的一个模块集成到A里面去。App B可以被打成aar包,已sdk的形式被app A使用,但是这就要对appB的结构进行修改,而且集成后aar包有问题的话修改也比较麻烦。所以这里使用了一个Android的组件化方式来实现。通过组件化方式,可以在做极少改动B的源码的情况下,把B集成到A里面去,而且对B的修改也非常方便,方便各个子模块的并行开发是组件化的主要优点之一。本文就简单介绍一下组件化开发中,如何把一个子app作为一个模块的方法。
以Android studio为IDE,首先在你的工程里面new一个module.
然后选择“Android Library”
然后一路next就可以了。之后就可以在新module里面开发子app了,开发方式和主app的方式一样,而我的项目中,直接把app B的源码覆盖掉新建的module就ok了,但是需要修改一下app B对应的build.gradle文件,把apply plugin: 'com.android. application'改成applyplugin: 'com.android.library',如果有applicationId还要把此项去掉,因为作为library是不允许有applicationId的。建立一个app作为一个module,做到这一步框架层面的已经完成了,但是要编译成功,可能还要解决一些问题,这里介绍一下我自己的经验。
一、遇到tools:replace="android:icon"问题
这个是因为你的主app的AndroidManifest.xml文件引用了android:icon标签,而你的子app的AndroidManifest.xml也引用了android:icon标签,同样的还有android:label和android:theme标签,解决办法就是在你的主app的AndroidManifest.xml的applicaton标签中添加tools:replace="android:icon,,android:theme, ,android:label",也有的是在module的AnroidManifest.xml添加tool:replace,本人倾向于后者,通过添加该标签,module的AndroidManifest文件不需要删除属性,不管是作为module还是application都没有问题。实践证明,一个项目可以同时存在两个application,你可以随意运行某个app
二、遇到java.lang.NoSuchFieldError:No static field xxx of type I in class Lcom/XX/R$id; or its superclasses。
这个错误的原因最可能就是你子app的某个资源和主app的资源文件的名字重合了,导致子app引用的其实是主app的资源,这时候只要把资源文件的名字改一下,和主app的资源文件的名字不一样就可以了。
三、子app变作Library的时候,有些语句可能会一起编译错误。比如在switch语句里面,
如果你的常量原来是R.id. 控件_id,在app里面,R.id.控件_id是可以作为常量的,但是作为Library,R.id.控件_id是不能作为常量的,这样就会引发编译错误,修改方法很简单,换成if语句就可以了。
四、在日常开发中,子app作为library是无法编译运行的,只能运行主app的话我们怎么实现并行开发呢。
解决办法就是修改配置文件,首先在工程的gradle.property文件里面添加一个变量isDebug = false,这个变量是String类型的。在Android项目中的任何一个build.gradle文件中都可以把gradle.properties中的常量读取出来。这样就可以在子app对应的build.gradle文件中这样写
if (isDebug.toBoolean()) {
apply plugin: 'com.android.application'
} else {
apply plugin: 'com.android.library'
}
这样在Debug模式下就能针对子app进行编译开发了,提高编译速度,提升开发效率。
五、module如何打包成aar的方法:
打开gradle,找到对应module下的Tasks/build/assemble,双击运行即可。打开对应module目录下的build\outputs\aar,就可以发现已经生成了release和debug两个版本的aar,使用release的即可。注意,如果module下有引用其他的aar,打包出来的aar并没有自动包含引用的aar,所以使用时,需要把所有的aar都放到工程里面去。