Android组件化的基本操作+ARouter的基本使用(动图演示)

一、Android组件化的基本操作

Android组件化是指将项目划分为多个模块,并且每个模块可以单独的作为app运行。有利于不同业务的解耦,并且可以提高编译速度,提高协作开发的效率。

1.从新建项目开始吧,取个简单的名字:Component:



建好之后长这样:


2.既然是要分模块,那我们先建几个模块:


本例中,我们新建了Base模块,First模块,Second模块,Base模块用来放置每个模块都要用到的公共内容,First模块和Second模块是功能模块。新建项目时自动生成的app模块作为一个壳模块,用来整合其他模块。

新建的模块中有很多测试的文件,如图:


笔者从事开发安卓一年多,尚未接触过单元测试,所以我们先把和测试有关的文件删掉,程序看起来会更加的简洁。(当然如果读者需要这些测试文件,将它们保留即可。)module中的versionCode和versionName也是可以删除的。


先切换到Project模式,再删除每个模块的androidTest文件夹、test文件夹以及build.gradle中测试有关的内容。(如果不切换到Project模式,直接在Android模式下删除androidTest文件夹和test文件夹的话,也可以删除这两个文件夹中的内容,但是无法删除这两个文件夹,就会导致有两个空文件夹,虽然对代码没有任何影响,但是笔者是一个代码强迫症患者,还是想把它们彻底删除...),将module中的versionCode和versionName也删除,只保留app模块中的versionCode和versionName。

3.gradle的统一管理


首先在项目根目录的build.gradle中,添加Sdk版本配置和依赖库的版本信息:

ext {
    cfg = [
            compileSdk       : 27,
            minSdk           : 15,
            targetSdk        : 27,
            versionCode      : 1,
            versionName      : "1.0"
    ]

    libs = [
            support             : "com.android.support:appcompat-v7:27.1.1",
            constraintLayout    : "com.android.support.constraint:constraint-layout:1.1.0"
    ]
}

添加了之后,就可以在模块的build.gradle中,使用cfg.compileSdk、libs.support等变量了。这里的cfg、libs、compileSdk、support都是变量名,名字可以任取。

3.1.我们把各个模块需要依赖的公共库添加到base模块的build.gradle中。

此时,base的build.gradle完整代码如下:

apply plugin: 'com.android.library'

android {
    compileSdkVersion cfg.compileSdk
    defaultConfig {
        minSdkVersion cfg.minSdk
        targetSdkVersion cfg.targetSdk
    }

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

}

dependencies {
    api fileTree(dir: 'libs', include: ['*.jar'])
    api libs.support
    api libs.constraintLayout
}

3.2.然后在first模块和second模块的build.gradle中,添加base模块依赖。

此时,first模块和second模块的build.gradle相同,如下:

apply plugin: 'com.android.library'

android {
    compileSdkVersion cfg.compileSdk
    defaultConfig {
        minSdkVersion cfg.minSdk
        targetSdkVersion cfg.targetSdk
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation project(':base')
}

3.3.在app模块的build.gradle中,添加base模块,first模块,second模块的依赖。

此时,app模块下的build.gradle代码如下:

apply plugin: 'com.android.application'

android {
    compileSdkVersion cfg.compileSdk
    defaultConfig {
        applicationId "com.simple.component"
        minSdkVersion cfg.minSdk
        targetSdkVersion cfg.targetSdk
        versionCode cfg.versionCode
        versionName cfg.versionName
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation project(':base')
    implementation project(':first')
    implementation project(':second')
}

注意base中添加依赖时需要使用api关键字,不能使用implementation关键字。因为implementation关键字引入的库是对外不开放的。(对外不开放的意思是指:在其他模块中引入base模块后,无法使用base模块中implementation引入的依赖库;api关键字引入的库是对外开放的。)

4.要让first模块能够单独运行,需要first模块有一个启动Activity,并且需要将first模块下的build.gradle中的apply plugin: 'com.android.library'改为apply plugin: 'com.android.application'

4.1.那么我们就来试试吧,做一些简单的修改,让first模块单独运行起来:


先是新建了一个Activity,注意这里命名不能和其他模块重复,所以我们带上模块名做区分,命名为FirstMainActivity。然后将FirstMainActivity作为启动Activity,然后将first模块下的build.gradle中的apply plugin: 'com.android.library'改为apply plugin: 'com.android.application',由于first模块变成了一个单独的可运行模块,所以app模块中不能将他作为库依赖进来了,所以我们先将app模块下的implementation project(':first')注释掉

切换到first模块运行:


4.2这时候会遇到崩溃,打开Log日志看到如下信息:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.simple.first/com.simple.first.FirstMainActivity}: java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.

指的是Activity必须有一个主题,那么我们就来给FirstMainActivity设置一个主题:


我们注意到,app模块下是有一个AppTheme主题的,我们把app模块下的styles文件和AppTheme中使用到的colors文件都移动到base模块下的values文件夹中,然后在first模块的AndroidManifest中,给application标签添加主题:android:theme="@style/AppTheme"(也可以只给FirstMainActivity添加主题,在application标签中添加主题会给first模块下所有的Activity都添加这个主题)。这时候再运行first模块就没有问题了。

app会使用默认的图标,app名字为包名:


4.3.如果要自己设置app的名字和图标等属性,照着app模块下AndroidManifest中的application标签中依样画葫芦即可:

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
注:

allowBackup是指此app是否允许备份用户数据,如果不需要的话最好关闭,网上说有开启它有安全风险

icon是指应用图标

roundIcon是指应用圆形图标

label是指应用名称

supportsRtl是指是否支持从右到左布局(Rtl是right-to-left的缩写),举个例子:如果在布局中使用了marginLeft属性,AndroidStudio就会提示我们:


可以看到,AndroidStudio建议我们增加android:layout_marginStart="16dp",这是由于有的国家是从右到左写字的(比如我们的阿拉伯兄弟),如果supportsRtl设置为true,布局中设置android:layout_marginStart="16dp",那么对于从右到左写字的国家,布局就会变成从右往左,方便他们使用。

5.通过第4点我们已经学会了怎么让模块单独运行,但是我们想要达到的效果是:让一个模块随时可以单独运行,也可以随时切换成总app的一个模块方便打包。接下来,我们通过一个标志位来处理这两种情况。


5.1.先在first模块的java文件夹下,新建debug文件夹,将第4步中first模块下的AndroidManifest复制到debug文件夹中,再将first模块的AndroidManifest改回成作为总app的一个模块时的样子。

5.2.在项目的gradle.properties中,新增isUniqueApp变量,设置为true。用isUniqueApp来标记功能模块是否作为独立的app。isUniqueApp = true时,表示功能模块作为独立的app运行,isUniqueApp = false时,表示功能模块作为总app的一个模块,不能单独运行。

5.3.在first模块的build.gradle中,将:

apply plugin: 'com.android.application'

改为

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

意思是:如果这个模块是作为单独app运行的,那么apply plugin: 'com.android.application';

如果这个模块是作为总app的一个模块,那么apply plugin: 'com.android.library'

5.4.在first模块的build.gradle中,添加:

sourceSets {
    main{
        if(isUniqueApp.toBoolean()){
            manifest.srcFile 'src/main/java/debug/AndroidManifest.xml'
        }else{
            manifest.srcFile 'src/main/AndroidManifest.xml'
            java{
                exclude 'debug/**'
            }
        }
    }
}

意思是:如果这个模块是作为单独app运行的,那么manifest资源使用src/main/java/debug/AndroidManifest.xml;

如果这个模块是作为总app的一个模块,那么manifest资源使用src/main/AndroidManifest.xml,并且排除debug文件夹中的内容

对second模块的操作和first模块一样。

5.5.将app模块下引入first、second模块依赖的代码改为:

if(!isUniqueApp.toBoolean()){
    implementation project(':first')
    implementation project(':second')
}

意思是:如果first模块和second模块是作为单独app运行的,那么不引入first、second模块;

如果first模块和second模块是作为总app的模块,那么引入first、second模块

6.为了标题和图标的统一,我们为first模块和second模块设置一个应用图标和应用名称:


先把app模块中和图标有关的图片移动到base模块,以保证每个模块都可以访问这些资源文件。然后给application标签设置label属性和icon属性

这样就完成了项目的组件化。


二、ARouter的基本使用

ARouter是阿里巴巴开源的路由框架,可以使用ARouter方便的进行Activity隐式跳转。

ARouter的Github地址为:https://github.com/alibaba/ARouter

1.引入ARouter


在项目的ext.libs中,添加:

arouterCompiler     : "com.alibaba:arouter-compiler:1.1.4",
arouterApi          : "com.alibaba:arouter-api:1.3.1"

在base模块,添加:

api libs.arouterApi

在first模块和second模块,添加:(需要跳转的每个模块都要添加)

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

dependencies {
    ...
    annotationProcessor libs.arouterCompiler
}

2.初始化ARouter


3.实现界面跳转:


3.1.先在FirstMainActivity中添加了路径:

@Route(path = "/first/main")

路径需要至少两级,第一级是指分组。

3.2.在MainActivity中添加跳转代码:

// 1. 应用内简单的跳转(通过URL跳转在'进阶用法'中)
ARouter.getInstance().build("/first/main").navigation();

3.3.在gradle.properties中将isUniqueApp设置为false,因为在组件化开发时,各个模块是独立的,只有非组件化模式才能实现跳转到不同的模块。

4.如果要跳转时需要带参数,代码为:

// 2. 跳转并携带参数
ARouter.getInstance().build("/first/main")
        .withLong("key1", 666L)
        .withString("key2", "888")
        .withObject("key3", Your_Data)
        .navigation();

其中,Your_Data是一个实现了序列化的对象。


运行程序,Log控制台可以看到:

com.simple.component D/FirstMainActivity: onCreate: 666
com.simple.component D/FirstMainActivity: onCreate: 888

以上,就是ARouter的基本使用。

参考文章:组件化在项目中的使用姿势:https://www.jianshu.com/p/ed845d796710

源码已上传:

https://github.com/wkxjc/StudyComponent

猜你喜欢

转载自blog.csdn.net/alpinistwang/article/details/80569550
今日推荐