Android 组件化必知必会

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xingxtao/article/details/85019381

什么是组件化?

组件化: 就是将一个 Application 的开发分成多个模块,每个模块都是一个组件(Module),开发的过程中我们可以只用专注自己开发的模块,进行单独调试,但在最终发布 apk 时,又可以将这些组件合并成一个统一的 app。
在这里插入图片描述

组件化环境搭建

实现组件化基本思路: 根据配置文件中的 isAloneRun 变量来决定该组件是作为 module 工程集成到 App 工程中,还是单独作为 app 工程独立运行。

组件作为 module 和 作为独立的 App 的不同的配置主要有:

  • 组件的 build.gradle 文件配置:作为 library 时配置为 apply plugin: 'com.android.library' 作为 app 时配置为 apply plugin: 'com.android.application'
  • 组件的 AndroidManifest.xml 文件配置: 作为 library 时,AndroidManifest.xml 文件中的 标签不配置 android:applicationName 属性;
    在这里插入图片描述

common_base 模块主要负责封装公共功能,例如 网络请求框架,图片加载框架,各种 utils ,为了防止重复依赖库的问题,所有的依赖库都放在该模块中进行加载,其他业务组件不做第三方库的依赖,只需依赖 common_base 公共库即可。

common_base 模块无论是在什么情况下都是作为 library 的形式存在的 ,其他的组件依赖它。

第一步: 为了方便管理第三方库的版本,在 project 目录下新建一个 config.gradle 文件(直接复制一份 build.gradle), 配置 SDK 版本和所用到的第三方库的版本,内容如下:

/**
 引用步骤:
 (1) 在 project 下的 build.gradle 文件第一行添加 apply from : "config.gradle"
 (2) 在各个 module 中用 implemetions rootProject.ext.dependencies['xxx'] 和 annotationProcessor rootProject.ext..dependencies['xxx']
 **/
ext {
    android = [
            applicationId    : 'com.xing.componentsample',
            compileSdkVersion: 28,
            buildToolsVersion: "28.0.3",
            minSdkVersion    : 15,
            targetSdkVersion : 28,
            versionCode      : 1,
            versionName      : "1.0"
    ]

    dependencies = [
            // support
            "appcompat-v7"        : "com.android.support:appcompat-v7:28.0.0",
            "design"              : "com.android.support:design:28.0.0",
            "support-v4"          : "com.android.support:support-v4:28.0.0",
            "cardview-v7"         : "com.android.support:cardview-v7:28.0.0",
            "annotations"         : "com.android.support:support-annotations:28.0.0",
            "recyclerview-v7"     : "com.android.support:recyclerview-v7:28.0.0",
            "gson"                : "com.google.code.gson:gson:2.2.4",
            "butterknife"         : "com.jakewharton:butterknife:8.8.1",
            "butterknife-compiler": "com.jakewharton:butterknife-compiler:8.8.1",
            "constraint-layout"   : "com.android.support.constraint:constraint-layout:1.1.3",
            "retrofit"            : "com.squareup.retrofit2:retrofit:2.4.0",
            "rxandroid"           : "io.reactivex.rxjava2:rxandroid:2.1.0",
            "rxjava"              : "io.reactivex.rxjava2:rxjava:2.2.2",
            "converter-gson"      : "com.squareup.retrofit2:converter-gson:2.4.0",
            "adapter-rxjava"      : "com.squareup.retrofit2:adapter-rxjava2:2.4.0",
            "okhttp"              : "com.squareup.okhttp3:okhttp:3.11.0",
            "logging-interceptor" : "com.squareup.okhttp3:logging-interceptor:3.11.0",
            "arouter-api"         : "com.alibaba:arouter-api:1.4.1",
            "arouter-compiler"    : "com.alibaba:arouter-compiler:1.2.2"
    ]
}

在 project 中的 build.gradle 文件中引入该 config.gradle 配置文件:

apply from: "config.gradle"

第二步: 在 common_base 模块中引入第三方库:

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    api rootProject.ext.dependencies['appcompat-v7']
    api rootProject.ext.dependencies['design']
    api rootProject.ext.dependencies['support-v4']
    api rootProject.ext.dependencies['cardview-v7']
    api rootProject.ext.dependencies['annotations']
    api rootProject.ext.dependencies['recyclerview-v7']
    api rootProject.ext.dependencies['constraint-layout']
    api rootProject.ext.dependencies['gson']
    api rootProject.ext.dependencies['constraint-layout']
    api rootProject.ext.dependencies['retrofit']
    api rootProject.ext.dependencies['rxandroid']
    api rootProject.ext.dependencies['rxjava']
    api rootProject.ext.dependencies['converter-gson']
    api rootProject.ext.dependencies['adapter-rxjava']
    api rootProject.ext.dependencies['okhttp']
    api rootProject.ext.dependencies['logging-interceptor']
    // butterknife
    api rootProject.ext.dependencies['butterknife']
    annotationProcessor rootProject.ext.dependencies['butterknife-compiler']
    // arouter
    api rootProject.ext.dependencies['arouter-api']
}

注意此处使用 api 而不是 implementions ,否则其他业务组件将引用不到这些第三方库。

第三步: 在 project 的 gradle.properties 文件中新增 isRunAlone 变量

# 标示各个业务组件是否以 application 单独运行,修改后需要同步才能生效
isRunAlone=false

在业务组件的 build.gradle 文件中,添加 common_base 公共库的依赖 ,并根据 isRunAlone 变量配置 apply plugin 是 application 还是 library , 以及加载不同的 AndroidManifest.xml 文件,配置内容如下:

// module_login/build.gradle 文件
if (isRunAlone.toBoolean()) {
    apply plugin: 'com.android.application'
} else {
    apply plugin: 'com.android.library'
}
apply plugin: 'com.jakewharton.butterknife'
android {
    // 也可以使用这种方式:rootProject.ext.android['compileSdkVersion']
    compileSdkVersion rootProject.ext.android.compileSdkVersion
    buildToolsVersion rootProject.ext.android.buildToolsVersion
    defaultConfig {
        minSdkVersion rootProject.ext.android.minSdkVersion
        targetSdkVersion rootProject.ext.android.targetSdkVersion
        versionCode rootProject.ext.android.versionCode
        versionName rootProject.ext.android.versionName

        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [AROUTER_MODULE_NAME: project.getName()]
                includeCompileClasspath = true
            }
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    sourceSets {
        main {
            if (isRunAlone.toBoolean()) {
                manifest.srcFile 'src/main/debug/AndroidManifest.xml'
            } else {
                manifest.srcFile 'src/main/AndroidManifest.xml'
                java {
                    // 全部 module 一起编译时剔除 debug 目录
                    exclude '**/debug/**'
                }
            }
        }
    }
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    // 依赖公共库
    implementation project(':common_base')
    // butterknife-compiler
    annotationProcessor rootProject.ext.dependencies['butterknife-compiler']
    // arouter-compiler
    annotationProcessor rootProject.ext.dependencies['arouter-compiler']
}

在这里插入图片描述

其中 AndroidManifest.xml文件的配置,在作为 library 时,不配置 applicationName 和 程序入口 Activity(如果整个 App 的入口 Activity 不是该 Activity )

<!--作为组件module被加载时,Manifest.xml中不能配置 application name -->
<application>
    <activity
        android:name=".activity.LoginActivity"
        android:screenOrientation="portrait">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

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


<!--作为 app 时,需要配置 application name 和程序入口-->
<application
    android:name=".app.LoginModuleApplication"
    android:allowBackup="true"
    android:fullBackupContent="true"
    android:icon="@drawable/login_ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme">

    <activity
        android:name=".activity.LoginActivity"
        android:screenOrientation="portrait">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

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

第四步: 各组件之间的跳转,由于各个组件之间没有依赖关系,所以通常需要借助 路由 来做跳转。

这里借助阿里 ARouter 路由;

gradle 配置:

android {
    defaultConfig {
        ........
        // Arouter路由配置
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [AROUTER_MODULE_NAME: project.getName()]
                includeCompileClasspath = true
            }
        }
    }
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    // 依赖公共库
    implementation project(':common_base')
    // arouter-compiler
    annotationProcessor rootProject.ext.dependencies['arouter-compiler']
}

开始跳转页面:

/**
 * 跳转主界面
 */
private void gotoMainActivity() {
    ARouter.getInstance().build("/main/activity").navigation();
    finish();
}

目标页面:

@Route(path = "/main/activity")
public class MainActivity extends BaseActivity {
    ........
}

集成注意点

ButterKnife 问题

在 project 的 build.gradle 添加 butterknife plugin,然后在所有用到 butterknife 的 library 中添加如下配置

在这里插入图片描述

apply plugin: 'com.jakewharton.butterknife'
...........
dependencies {
	// butterknife-compiler
    annotationProcessor rootProject.ext.dependencies['butterknife-compiler']
}

在 library 中集成 butterknife,绑定控件时,需要使用 R2 代替 R, 以及在 library 中控件的 id 不是常量,所以在不能使用 switch 语句。

在这里插入图片描述

在这里插入图片描述

资源文件命名冲突

为了避免资源文件冲突问题,最好以该模块名为文件前缀进行区分。

在这里插入图片描述

源码地址: https://github.com/xing16/ComponentSample

猜你喜欢

转载自blog.csdn.net/xingxtao/article/details/85019381