Android高级进阶之-组件化开发实现

组件化开发的思路是:
把项目的各个模块用library形式抽取出来,每个模块负责自己的业务,在开发阶段,各个模块可以单独打包成apk运行。最终的项目用一个壳application把这些library模块整合到一起,可以输出一个完整的apk。

image.png

组件化的实现步骤:
1.项目根目录创建一个文件“config.gradle”:

ext {
    isModule = true
}

2.项目根目录的build.gradle中引用刚刚创建的"config.gradle":

//实现赋值与引用
apply from: 'config.gradle'

buildscript {
    //....
}

到这一步,就是告诉gradle的rootProject(项目根目录的build.gradle就会被翻译成为rootProject),添加一个字典isModule = true 。

3.创建一个lib module项目”module1“。
4.修改module1 的build.gradle文件(module的build.gradle也会被翻译成为project,每个project都会持有rootProject对象,可以引用rootProject的属性):

apply plugin: 'com.android.library'

if (isModule) {
    apply plugin: 'com.android.library'
} else {
    apply plugin: 'com.android.application'
}

这样,当修改isModule后,重新编译,module1就会按照 library或者application 的方式加到项目中,为library就说明它是一个库,为application就说明它是可打包apk的app项目。
5.在壳项目”app“中修改build.gradle:

dependencies {
    if(isModule){
        implementation project(path: ':module1')
    }
}

效果是:当module1以application方式运行时,壳app就不去依赖module1。

到这里,我们就可以通过修改”confi.gradle"来切换"module1"的工作方式。

补充:
”module1“作为application运行时,必须要告诉它的AndroidManifest.xml 指明一个LAUNCHER入口:

<activity android:name=".XXXXXX">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
</activity>

但是作为lib运行时,我们没有这个要求。因此,”module1“需要根据isModule来指定不同的AndroidManifest.xml文件。
lib运行时,src/main/AndroidManifest.xml 写成:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="carlwu.top.module1">
    //...
</manifest>

application运行时,src/cmp/AndroidManifest.xml 写成:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="carlwu.top.module1">

    <application
        android:theme="@style/Theme.AppCompat.Light.DarkActionBar">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

我们可以在module1 的build.gradle文件中加上这样的配置:

android {
    //...
    sourceSets {
        main {
            if (!isModule) {
                manifest.srcFile 'src/cmp/AndroidManifest.xml'
            }
        }
    }
}

告诉编译器,application方式运行module1时,加载符合application运行要求的AndroidManifest.xml文件。

有时我们把module1当成application运行时,需要指定自定义的Application类,那么就需要把src/cmp/AndroidManifest.xml 这么写:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="carlwu.top.module1">

    <application
        android:name=".MyApplication"//指定自定义的Application
        android:theme="@style/Theme.AppCompat.Light.DarkActionBar">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

我们就需要在module1的java目录下添加MyApplication这个类,但是如果不做处理,module1当lib被app依赖也会把类MyApplication依赖进去,这个类实际上是不需要被依赖的,最好是编译都不要参与。我们是有办法的。
修改module1的build.gradle:

android {
    //...
    sourceSets {
        main {
            if (!isModule) {
                java.srcDirs 'src/cmp/java'
                manifest.srcFile 'src/cmp/AndroidManifest.xml'
            }
        }
    }
}

意思就是告诉编译器,module1除了默认的src/main/java 目录外,还可以添加 src/cmp/java 这个目录最为源码目录,里面的类也会参与编译打包。
效果如下:


image.png
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。