Skip to content

前言

最近在练习多模块,基本上是从0开始的,中途遇到了好多问题报错等等,故开个这篇文章记录总结一下,以防后面继续踩坑qaq。

是用的玩Android,基本上是把寒假写的东西搬了过来重构了一下,技术上没什么高级的。。。

github项目地址:https://github.com/generalio/WanAndroidMulti

相较于寒假的优化如下:

  • 对网络是否链接进行了判断
  • 使用MVVM+Retrofit+RxJava+Jetpack的结构进行开发(不敢使用协程,还不太熟悉)
  • 使用了paging3进行分页加载
  • 搜索页面能进行模糊搜索
  • 把整体页面套了个androidx.coordinatorlayout.widget.CoordinatorLayout,在列表进行滑动时能有很好的加载逻辑

文章的收藏功能懒得写了,太麻烦了并且容易出一些奇奇怪怪的bug。

多模块构建

多模块,就是将自己的app的许多界面或者不同的功能拆成一个个单个的模块,将项目进行拆分,解耦。

多模块分为lib,module,api(没怎么用过)这几个模块类型。

新建模块

新建lib模块

这里我们选择Android LibraryModule name改为lib_xxx,注意还要将Package name.lib_xxx改成.lib.xxx,这样就新建好了一个lib模块了。

然后在主模块的build.gradle.kts中依赖一下就好了:

kotlin
implementation(project(":lib_base"))

新建module模块

步骤与上面一样,但是我们要选择第一个Phone & Tablet,然后进行一些改动:

删除res中的不必要的东西:

然后删除string.xml中的app_name.修改AndroidMainfest.xml:

xml
<application>
    <activity
        android:name=".TestActivity"
        android:exported="true">
    </activity>
</application>

最后再build.gradle.kts中:

kotlin
plugins {
    //alias(libs.plugins.android.application) 这是原来的
    alias(libs.plugins.kotlin.android)
    id("com.android.library") //换成这个library
}
android {
    namespace = "com.generals.module.main"
    compileSdk = 35

    defaultConfig {
        //applicationId = "com.generals.module.main" 删除掉
        minSdk = 30
        targetSdk = 34
        //versionCode = 1 删除掉
        //versionName = "1.0" 删除掉

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            isMinifyEnabled = false
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_11
        targetCompatibility = JavaVersion.VERSION_11
    }
    kotlinOptions {
        jvmTarget = "11"
    }
}

这样就好了,然后同样在主模块中依赖一下:

kotlin
implementation(project(":module_test"))

这样就构建好了module模块。

总的来说,lib模块通常是存放一些基类和工具类,比如baseactivity,basefragment以及一些工具的封装等等。

module模块通常就是一个界面,比如main,login等,在这些模块中我们通常要将lib_base依赖进去。

模块间的通信

模块间的通信,同一层级中的几个模块通常不会互相依赖,所以不能直接进行通信,于是我们用到了Arouter。

ARouter 是阿里2017年开源的页面路由框架,官方对这个框架的定义是 ARouter 是阿里巴巴开源的 Android 平台中对页面、服务提供路由功能的中间件,提倡的是简单且够用。

导入依赖:

toml
arouter-api = { module = "com.alibaba:arouter-api", version.ref = "arouter" }
arouter-compiler = { module = "com.alibaba:arouter-compiler", version.ref = "arouter" }

这是在gradle/libs.versions.xml下的依赖统一管理方式。

在模块中添加依赖和配置:

kotlin
plugins {
    //alias(libs.plugins.android.application)
    alias(libs.plugins.kotlin.android)
    id("com.android.library")
    kotlin("kapt")
}

kapt {
    arguments {
        arg("AROUTER_MODULE_NAME", project.name)
    }
}
...
dependencies {
    
    ...
    implementation(libs.arouter.api)
    kapt(libs.arouter.compiler)

    implementation(project(":lib_base"))
}

初始化SDK,在你的全局Application中(如BaseApp.kt):

kotlin
class BaseApp : Application() {
    companion object {
        @SuppressLint("StaticFieldLeak")
        lateinit var context : Context
    }

    private val isDebug = true

    override fun onCreate() {
        super.onCreate()

        //获取全局context
        context = applicationContext

        //Arouter的初始化
        if(isDebug) {
            ARouter.openLog()
            ARouter.openDebug()
        }
        ARouter.init(this)
    }
}

添加注解:

kotlin
// 这里的路径需要注意的是至少需要有两级,/xx/xx
@Route(path = "/test/test")
class TestActivity : AppCompatActivity() {
...
//获取数据
var key3 = getIntent().getStringExtra("key3")
}

发起路由操作:

kotlin
// 1. 应用内简单的跳转
ARouter.getInstance().build("/test/activity").navigation()
// 2. 跳转并携带参数
ARouter.getInstance().build("/test/activity")
.withLong("key1", 666L)
.withString("key3", "888")
.withObject("key4", new Test("Jack", "Rose"))
.withBundle("bundle", bundle)
.navigation()
// 获取Fragment
val fragment:Fragment = (Fragment)
ARouter.getInstance().build("/test/fragment").navigation()

还有一些拦截器的操作(比如跳转时处理是否登录),就不多介绍(感觉也不太常用)。

在使用Arouter时,打包编译时可能会报错:

提示导入了support包与现在的冲突了,这是Arouter导入时会自动引入的东西,只需要在根目录下的gradle.properties文件下加入下面的代码:

properties
# Arouter中包含support包,使用该选项后Android插件会通过重写第三方库的二进制文件,自动将这些库迁移为AndroidX
# https://developer.android.com/jetpack/androidx/migrate
android.enableJetifier=true

这样就解决了。

然后剩下的就跟普通的差不多了,编译打包时全量打包就好了不用单模块调试。单模块调试可能出些奇奇怪怪的问题(因为你这个模块依赖了些其他模块,而单模块调试不会将这些模块导进去)。