【Android 组件化】使用 ARoute 实现组件化 ( 完整组件化项目框架 )

简介: 【Android 组件化】使用 ARoute 实现组件化 ( 完整组件化项目框架 )

一、ARoute 引入


使用 ARouter 第三方库实现组件化 : https://github.com/alibaba/ARouter


ARoute 是阿里的开源库 ;


创建项目 , 项目中有 3 33 个 Module , 1 11 个主模块 app , 2 22 个依赖库 module1 和 module2 ;

9.png



在 app , module1 , module2 , 3 33 个模块的 build.gradle 中 , 都要进行如下配置 ;



在 build.gradle 下的 " android / defaultConfig " 层级添加配置 :


android {
    defaultConfig {
        ...
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [AROUTER_MODULE_NAME: project.getName()]
            }
        }
    }
}


在 build.gradle 下的 " dependencies " 层级添加 ARoute 依赖 :


// 替换成最新版本, 需要注意的是api
    // 要与compiler匹配使用,均使用最新版可以保证兼容
    api 'com.alibaba:arouter-api:1.5.1'
    annotationProcessor 'com.alibaba:arouter-compiler:1.5.1'


3 33 模块间的依赖关系 : app 模块依赖剩余两个模块 , 模块之间不发生依赖关系 ;

implementation project(path: ':module1')
implementation project(path: ':module2')

二、3 个模块的界面跳转


1、app 模块注解、app 跳转到 module1 模块


app 模块 : 使用 @Route(path = "/app/MainActivity") 注解标注 Activity 类 , 界面按钮点击方法跳转到 module1 中的 Activity 界面中 ;



代码示例 :


package kim.hsl.component;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.alibaba.android.arouter.launcher.ARouter;
// 在支持路由的页面上添加注解(必选)
// 这里的路径需要注意的是至少需要有两级,/xx/xx
@Route(path = "/app/MainActivity")
public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    public void onClick(View view) {
        Log.i(TAG, "跳转到 Module1");
        ARouter.getInstance().build("/module1/Module1Activity").navigation();
        finish();
    }
}



2、module1 模块注解、module1 跳转到 module2 模块


module1 模块跳转到 module2 模块 , 这两个模块之间互相没有依赖关系 ;


module1 模块使用 @Route(path = "/module1/Module1Activity") 注解标注 ,



代码示例 :


package kim.hsl.module1;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.alibaba.android.arouter.launcher.ARouter;
@Route(path = "/module1/Module1Activity")
public class Module1Activity extends AppCompatActivity {
    private static final String TAG = "Module1Activity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_module1);
    }
    public void onClick(View view) {
        Log.i(TAG, "跳转到 Module2");
        ARouter.getInstance().build("/module2/Module2Activity").navigation();
        finish();
    }
}


3、module2 模块注解、module2 跳转到 app 模块


代码示例 :


package kim.hsl.module2;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.alibaba.android.arouter.launcher.ARouter;
@Route(path = "/module2/Module2Activity")
public class Module2Activity extends AppCompatActivity {
    private static final String TAG = "Module2Activity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_module2);
    }
    public void onClick(View view) {
        Log.i(TAG, "跳转到 app");
        ARouter.getInstance().build("/app/MainActivity").navigation();
        finish();
    }
}


4、跳转效果


20210529133239910.gif






三、组件化配置


1、全局配置


全局配置 :


isModuleMode 是最终要的配置 , 通过该配置的 true / false 设置当前是否开启组件化 ,


集成模式 true ( 默认模式 , 模块化 )

组件模式 false ( 组件化 )

androidConfig 用于统一管理各个 Module 中的版本号 , 如编译版本号 , 最小版本号 , 目标版本号 ;


applicationId 用于保存各个模块的包名 , 尤其是 module 依赖库的包名 , 组件化的状态下 , 该 module 需要独立运行 , 必须配置一个 applicationId 包名 ;


dependencies 用于统一管理各个模块之间的依赖库 , 避免管理分散 ;


// ext 是 extension 扩展的含义
// ext 后的 {} 花括号 , 是闭包 ,
ext{
    // 是否是模块化模式
    // 集成模式 true ( 默认模式 , 模块化 )
    // 组件模式 false ( 组件化 )
    isModuleMode = true
    // 定义 android 变量 , 类型是字典 Map 集合
    // 其中定义了若干键值对集合
    androidConfig = [
            compileSdkVersion : 30,
            minSdkVersion : 18,
            targetSdkVersion : 30,
            versionCode : 1,
            versionName : "1.0"
    ]
    applicationId = [
            "app" : "kim.hsl.component",
            "module1" : "kim.hsl.module1",
            "module2" : "kim.hsl.module2",
    ]
    // androidx 版本号
    androidxVersion = "1.3.0"
    constraintlayoutVersion = "2.0.4"
    materialVersion = "1.3.0"
    // 统一管理依赖库
    dependencies = [
            // ${} 表示引用之前定义的变量
            "appcompat" : "androidx.appcompat:appcompat:${androidxVersion}",
            "constraintlayout" : "androidx.constraintlayout:constraintlayout:${constraintlayoutVersion}",
            "material" : "com.google.android.material:material:${materialVersion}"
    ]
}



2、工程下的 build.gradle 配置


在总的 build.gradle 配置中 , 引入上述全局配置 , 其作用就相当于将上述全局配置原封不动拷贝过来 ;


apply from: "component.gradle"

1


完整配置 :


// Top-level build file where you can add configuration options common to all sub-projects/modules.
// 将 component.gradle 配置文件中的内容导入到该位置
// 相当于引入头文件
apply from: "component.gradle"
buildscript {
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:4.1.0"
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}
allprojects {
    repositories {
        google()
        jcenter()
    }
}
task clean(type: Delete) {
    delete rootProject.buildDir
}


3、app 模块下的 build.gradle 配置


在 app 模块中重点关注 , 在组件模式下 , 一定不能引入依赖库 , 否则会报错 , 因为组件模式下这两个依赖库是两个可运行的独立应用 ;


dependencies {
    if (isModuleMode){
        // 集成模式下才能引用这两个 Library Module
        implementation project(path: ':module1')
        implementation project(path: ':module2')
    }


版本号 , applicationId , 依赖库 统一管理 :


从 Project 级别的配置中获取变量 :


def androidConfig = rootProject.ext.androidConfig
def appId = rootProject.ext.applicationId
def dep = rootProject.ext.dependencies


版本号 和 applicationId 统一管理 :


android {
    compileSdkVersion androidConfig.compileSdkVersion
    defaultConfig {
        applicationId appId["app"]
        minSdkVersion androidConfig.minSdkVersion
        targetSdkVersion androidConfig.targetSdkVersion
        versionCode androidConfig.versionCode
        versionName androidConfig.versionName
    }


依赖库统一管理 :


dependencies {
    //implementation 'androidx.appcompat:appcompat:1.3.0'
    //implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    //implementation 'com.google.android.material:material:1.3.0'
    implementation dep.appcompat
    implementation dep.constraintlayout
    implementation dep.material
}


完整配置 :


plugins {
    id 'com.android.application'
}
def androidConfig = rootProject.ext.androidConfig
def appId = rootProject.ext.applicationId
def dep = rootProject.ext.dependencies
android {
    compileSdkVersion androidConfig.compileSdkVersion
    buildToolsVersion "30.0.3"
    defaultConfig {
        applicationId appId["app"]
        minSdkVersion androidConfig.minSdkVersion
        targetSdkVersion androidConfig.targetSdkVersion
        versionCode androidConfig.versionCode
        versionName androidConfig.versionName
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        // ARoute 需要的配置
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [AROUTER_MODULE_NAME: project.getName()]
            }
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}
dependencies {
    //implementation 'androidx.appcompat:appcompat:1.3.0'
    //implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    //implementation 'com.google.android.material:material:1.3.0'
    implementation dep.appcompat
    implementation dep.constraintlayout
    implementation dep.material
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
    // 替换成最新版本, 需要注意的是api
    // 要与compiler匹配使用,均使用最新版可以保证兼容
    api 'com.alibaba:arouter-api:1.5.1'
    annotationProcessor 'com.alibaba:arouter-compiler:1.5.1'
    if (isModuleMode){
        // 集成模式下才能引用这两个 Library Module
        implementation project(path: ':module1')
        implementation project(path: ':module2')
    }
}



四、Module 模块的组件化配置


Module 模块的配置比较复杂 ;


首先 , Module 模块在组件模式下是可以独立运行的应用 , 必须有一个入口 Activity ; 但是 Module 下的清单文件是这样的 :


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="kim.hsl.module1">
    <application>
        <activity android:name=".Module1Activity"></activity>
    </application>
</manifest>


这就需要为其单独配置一个清单文件 , 并且还要兼容在组件模式下能适用原来的这个清单文件 ;


此外还需要为其配置 Application 类 , 需要为其单独指定 Java 文件 , 并且在模块化模式中 , 不使用该文件 ;


1、创建组件模式下使用的类和清单文件


在 module1 下创建 组件模式 时使用的 Application 类和清单文件 ;


9.png



Application 类如下 :


package kim.hsl.module1;
import android.app.Application;
public class Module1Application extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
    }
}


清单文件如下 :


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="kim.hsl.module1">
    <application
        android:name=".Module1Application"
        android:allowBackup="true"
        android:supportsRtl="true"
        android:theme="@style/Theme.MaterialComponents.DayNight.DarkActionBar">
        <activity android:name=".Module1Activity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>


在 build.gradle 中 " android / defaultConfig / sourceSets " 下配置相关资源文件 , 如果在组件模式下 , 使用 manifest.srcFile 配置组件模式下的清单文件 , 使用 java.srcDirs 配置组件模式下使用的 Java 源文件 ;


这些配置在 集成模式 下都失效 , 因此使用 isModuleMode 进行判定当前是 组件模式 还是 集成模式 ;


android {
    defaultConfig {
        if (!isModuleMode){
            // 组件模式 : 必须配置 applicationId
            applicationId appId["module1"]
        }
        // 资源配置
        sourceSets{
            main{
                if (!isModuleMode){
                    // 组件化模式下使用 ComponentAndroidManifest.xml 作为清单文件
                    manifest.srcFile 'src/main/component/AndroidManifest.xml'
                    // 配置额外的 Java 源文件目录
                    java.srcDirs 'src/main/component/java', 'src/main/java'
                }else{
                    // 集成模式 下使用默认设置
                }
            }
        }
  }
}


2、动态切换 集成模式 / 组件模式


在 module 中需要考虑 集成模式 / 组件模式 动态切换问题 , 当 isModuleMode 设置为 true 时 , 当前是集成模式 , module 模块作为 app 模块的依赖库进行编译 , 因此需要加载 apply plugin: 'com.android.library' 插件 ;


当 isModuleMode 设置为 false 时 , 是 组件模式 , 每个 module 都是可以独立运行的应用 , 需要加载 apply plugin: 'com.android.application' 插件 ;



代码示例 :


// 根据 isModuleMode 动态切换 集成模式 / 组件模式
if (isModuleMode){
    // 集成模式
    apply plugin: 'com.android.library'
}else{
    // 组件模式
    apply plugin: 'com.android.application'
}


此外 , 如果是 组件模式 , module 是可以独立运行的应用 , 必须为其配置 applicationId ;


android {
    defaultConfig {
        if (!isModuleMode){
            // 组件模式 : 必须配置 applicationId
            applicationId appId["module2"]
        }
  }
}




3、module1 完整的 build.gradle 配置文件


// 根据 isModuleMode 动态切换 集成模式 / 组件模式
if (isModuleMode){
    // 集成模式
    apply plugin: 'com.android.library'
}else{
    // 组件模式
    apply plugin: 'com.android.application'
}
def androidConfig = rootProject.ext.androidConfig
def appId = rootProject.ext.applicationId
def dep = rootProject.ext.dependencies
android {
    compileSdkVersion androidConfig.compileSdkVersion
    buildToolsVersion "30.0.3"
    defaultConfig {
        if (!isModuleMode){
            // 组件模式 : 必须配置 applicationId
            applicationId appId["module1"]
        }
        minSdkVersion androidConfig.minSdkVersion
        targetSdkVersion androidConfig.targetSdkVersion
        versionCode androidConfig.versionCode
        versionName androidConfig.versionName
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        consumerProguardFiles "consumer-rules.pro"
        // 资源配置
        sourceSets{
            main{
                if (!isModuleMode){
                    // 组件化模式下使用 ComponentAndroidManifest.xml 作为清单文件
                    manifest.srcFile 'src/main/component/AndroidManifest.xml'
                    // 配置额外的 Java 源文件目录
                    java.srcDirs 'src/main/component/java', 'src/main/java'
                }else{
                    // 集成模式 下使用默认设置
                }
            }
        }
        // ARoute 需要的配置
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [AROUTER_MODULE_NAME: project.getName()]
            }
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}
dependencies {
    //implementation 'androidx.appcompat:appcompat:1.3.0'
    //implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    //implementation 'com.google.android.material:material:1.3.0'
    implementation dep.appcompat
    implementation dep.constraintlayout
    implementation dep.material
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
    // 替换成最新版本, 需要注意的是api
    // 要与compiler匹配使用,均使用最新版可以保证兼容
    api 'com.alibaba:arouter-api:1.5.1'
    annotationProcessor 'com.alibaba:arouter-compiler:1.5.1'
}



4、module2 完整的 build.gradle 配置文件


module1 与 module2 的配置项基本相同 ;


// 根据 isModuleMode 动态切换 集成模式 / 组件模式
if (isModuleMode){
    // 集成模式
    apply plugin: 'com.android.library'
}else{
    // 组件模式
    apply plugin: 'com.android.application'
}
def androidConfig = rootProject.ext.androidConfig
def appId = rootProject.ext.applicationId
def dep = rootProject.ext.dependencies
android {
    compileSdkVersion androidConfig.compileSdkVersion
    buildToolsVersion "30.0.3"
    defaultConfig {
        if (!isModuleMode){
            // 组件模式 : 必须配置 applicationId
            applicationId appId["module2"]
        }
        minSdkVersion androidConfig.minSdkVersion
        targetSdkVersion androidConfig.targetSdkVersion
        versionCode androidConfig.versionCode
        versionName androidConfig.versionName
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        consumerProguardFiles "consumer-rules.pro"
        // 资源配置
        sourceSets{
            main{
                if (!isModuleMode){
                    // 组件化模式下使用 ComponentAndroidManifest.xml 作为清单文件
                    manifest.srcFile 'src/main/component/AndroidManifest.xml'
                    // 配置额外的 Java 源文件目录
                    java.srcDirs 'src/main/component/java', 'src/main/java'
                }else{
                    // 集成模式 下使用默认设置
                }
            }
        }
        // ARoute 需要的配置
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [AROUTER_MODULE_NAME: project.getName()]
            }
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}
dependencies {
    //implementation 'androidx.appcompat:appcompat:1.3.0'
    //implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    //implementation 'com.google.android.material:material:1.3.0'
    implementation dep.appcompat
    implementation dep.constraintlayout
    implementation dep.material
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
    // 替换成最新版本, 需要注意的是api
    // 要与compiler匹配使用,均使用最新版可以保证兼容
    api 'com.alibaba:arouter-api:1.5.1'
    annotationProcessor 'com.alibaba:arouter-compiler:1.5.1'
}



5、module1 独立运行效果


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="kim.hsl.module1">
    <application
        android:name=".Module1Application"
        android:allowBackup="true"
        android:supportsRtl="true"
        android:theme="@style/Theme.MaterialComponents.DayNight.DarkActionBar">
        <activity android:name=".Module1Activity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>


清单文件中设置的主题是黑色的 ;

9.png



6、module2 独立运行效果


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="kim.hsl.module2">
    <application
        android:name=".Module2Application"
        android:allowBackup="true"
        android:supportsRtl="true"
        android:theme="@style/Theme.MaterialComponents.DayNight.DarkActionBar">
        <activity android:name=".Module2Activity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>


清单文件中设置的主题是黑色的 ;


9.png



目录
相关文章
|
3月前
|
Java Android开发 Swift
安卓与iOS开发对比:平台选择对项目成功的影响
【10月更文挑战第4天】在移动应用开发的世界中,选择合适的平台是至关重要的。本文将深入探讨安卓和iOS两大主流平台的开发环境、用户基础、市场份额和开发成本等方面的差异,并分析这些差异如何影响项目的最终成果。通过比较这两个平台的优势与挑战,开发者可以更好地决定哪个平台更适合他们的项目需求。
133 1
|
3月前
|
前端开发 JavaScript 测试技术
android做中大型项目完美的架构模式是什么?是MVVM吗?如果不是,是什么?
android做中大型项目完美的架构模式是什么?是MVVM吗?如果不是,是什么?
157 2
|
3月前
|
XML Java 数据库
安卓项目:app注册/登录界面设计
本文介绍了如何设计一个Android应用的注册/登录界面,包括布局文件的创建、登录和注册逻辑的实现,以及运行效果的展示。
277 0
安卓项目:app注册/登录界面设计
|
4天前
|
Dart 前端开发 Android开发
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
4月前
|
IDE Android开发 iOS开发
探索Android与iOS开发的差异:平台选择对项目成功的影响
【9月更文挑战第27天】在移动应用开发的世界中,Android和iOS是两个主要的操作系统平台。每个系统都有其独特的开发环境、工具和用户群体。本文将深入探讨这两个平台的关键差异点,并分析这些差异如何影响应用的性能、用户体验和最终的市场表现。通过对比分析,我们将揭示选择正确的开发平台对于确保项目成功的重要作用。
|
2月前
|
前端开发 JavaScript 测试技术
android做中大型项目完美的架构模式是什么?是MVVM吗?如果不是,是什么?
在 Android 开发中,选择合适的架构模式对于构建中大型项目至关重要。常见的架构模式有 MVVM、MVP、MVI、Clean Architecture 和 Flux/Redux。每种模式都有其优缺点和适用场景,例如 MVVM 适用于复杂 UI 状态和频繁更新,而 Clean Architecture 适合大型项目和多平台开发。选择合适的架构应考虑项目需求、团队熟悉度和可维护性。
69 6
|
2月前
|
算法 JavaScript Android开发
|
2月前
|
开发框架 Dart Android开发
安卓与iOS的跨平台开发:Flutter框架深度解析
在移动应用开发的海洋中,Flutter作为一艘灵活的帆船,正引领着开发者们驶向跨平台开发的新纪元。本文将揭开Flutter神秘的面纱,从其架构到核心特性,再到实际应用案例,我们将一同探索这个由谷歌打造的开源UI工具包如何让安卓与iOS应用开发变得更加高效而统一。你将看到,借助Flutter,打造精美、高性能的应用不再是难题,而是变成了一场创造性的旅程。
|
3月前
|
Java 程序员 API
Android|集成 slf4j + logback 作为日志框架
做个简单改造,统一 Android APP 和 Java 后端项目打印日志的体验。
168 1
|
3月前
|
前端开发 JavaScript 测试技术
Android适合构建中大型项目的架构模式全面对比
Android适合构建中大型项目的架构模式全面对比
61 2

热门文章

最新文章