前言
最近在练习多模块,基本上是从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 Library
,Module name
改为lib_xxx
,注意还要将Package name
的.lib_xxx
改成.lib.xxx
,这样就新建好了一个lib模块了。
然后在主模块的build.gradle.kts
中依赖一下就好了:
implementation(project(":lib_base"))
新建module模块
步骤与上面一样,但是我们要选择第一个Phone & Tablet
,然后进行一些改动:
删除res中的不必要的东西:
然后删除string.xml
中的app_name
.修改AndroidMainfest.xml
:
<application>
<activity
android:name=".TestActivity"
android:exported="true">
</activity>
</application>
最后再build.gradle.kts
中:
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"
}
}
这样就好了,然后同样在主模块中依赖一下:
implementation(project(":module_test"))
这样就构建好了module模块。
总的来说,lib模块通常是存放一些基类和工具类,比如baseactivity
,basefragment
以及一些工具的封装等等。
module模块通常就是一个界面,比如main,login等,在这些模块中我们通常要将lib_base依赖进去。
模块间的通信
模块间的通信,同一层级中的几个模块通常不会互相依赖,所以不能直接进行通信,于是我们用到了Arouter。
ARouter 是阿里2017年开源的页面路由框架,官方对这个框架的定义是 ARouter 是阿里巴巴开源的 Android 平台中对页面、服务提供路由功能的中间件,提倡的是简单且够用。
导入依赖:
arouter-api = { module = "com.alibaba:arouter-api", version.ref = "arouter" }
arouter-compiler = { module = "com.alibaba:arouter-compiler", version.ref = "arouter" }
这是在gradle/libs.versions.xml
下的依赖统一管理方式。
在模块中添加依赖和配置:
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
):
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)
}
}
添加注解:
// 这里的路径需要注意的是至少需要有两级,/xx/xx
@Route(path = "/test/test")
class TestActivity : AppCompatActivity() {
...
//获取数据
var key3 = getIntent().getStringExtra("key3")
}
发起路由操作:
// 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
这样就解决了。
然后剩下的就跟普通的差不多了,编译打包时全量打包就好了不用单模块调试。单模块调试可能出些奇奇怪怪的问题(因为你这个模块依赖了些其他模块,而单模块调试不会将这些模块导进去)。