基于 WanAndroid 开放 API 构建的多模块 Android 客户端,采用 MVVM 架构,参考 Now in Android 项目的 build-logic 约定插件方式进行构建。
- 首页文章列表(下拉刷新 / 上拉加载更多)
- Banner 轮播
- 公众号列表及文章浏览
- 导航分类
- 登录 / 注册
- 文章详情 WebView 浏览
| 类别 | 技术 |
|---|---|
| 语言 | Kotlin 2.1.0 |
| 构建 | Gradle 8.9 · AGP 8.7.2 · Convention Plugins |
| 最低版本 | minSdk 26 · targetSdk 36 · compileSdk 35 |
| 网络 | Retrofit 2.11.0 · OkHttp 5.3.2 · Kotlinx Serialization 1.7.3 |
| 异步 | RxJava 3 → LiveData |
| 图片 | Glide 5.0.5 |
| 模块通信 | ARouter 1.5.2 |
| 调试 | LeakCanary 2.14(仅 Debug) |
WanAndroid_Multi/
├── app/ # 壳工程,组装所有模块
├── build-logic/
│ └── convention/ # 约定插件(manager.library / manager.feature / manager.application)
├── core/
│ ├── base/ # BaseApp · BaseActivity · BaseFragment · BaseViewModel
│ ├── config/ # 路由表 RouteTable · 全局常量
│ └── util/ # 网络层 · ServiceManager · 扩展函数
├── feature/
│ ├── login/
│ │ ├── api_login/ # ILoginService 接口(对外暴露)
│ │ └── (login impl) # 登录功能实现
│ ├── main/ # 首页 · 公众号 · 导航
│ └── webview/
│ ├── api_webview/ # IWebviewService 接口(对外暴露)
│ └── (webview impl) # WebView 功能实现
└── gradle/
└── libs.versions.toml # 版本目录(统一依赖管理)
┌─────────────────────────────────────────────┐
│ app │
├──────────┬──────────────┬───────────────────┤
│ login │ main │ webview │ ← feature 层
├──────────┴──────────────┴───────────────────┤
│ api_login api_webview │ ← api 层(仅接口)
├─────────────────────────────────────────────┤
│ base · config · util │ ← core 层
└─────────────────────────────────────────────┘
核心解耦规则: feature 模块之间不直接依赖,只依赖对方的 api_xxx 模块。api_xxx 模块仅包含接口定义和路由常量,不包含任何实现。
View (Activity/Fragment)
↕ observe LiveData
ViewModel
↓ call
Repository (object)
↓ Retrofit
Service (interface) → API → ApiWrapper<T> → subscribeApi DSL
所有路由路径定义在 core/config 的 RouteTable.kt 中:
const val LOGIN_ENTRY = "/login/entry"
const val MAIN_ENTRY = "/main/entry"
const val WEBVIEW_ENTRY = "/webview/entry"页面跳转:
ServiceManager.activity(MAIN_ENTRY)跨模块服务调用:
// api_login 中定义接口
interface ILoginService : IProvider {
fun getData(): Data?
val liveData: LiveData<Data>
}
// login 模块中实现
@Route(path = LOGIN_SERVICE)
class LoginServiceImpl : ILoginService { ... }
// main 模块中消费(只依赖 api_login,不依赖 login)
ServiceManager<ILoginService>(LOGIN_SERVICE).liveData.observe(viewLifecycleOwner) { data -> }位于 core/util,基于 Retrofit + RxJava + Kotlinx Serialization:
RetrofitHelper— 单例 Retrofit,Cookie 自动持久化ApiWrapper<T>— 统一响应包装,errorCode == 0为成功,-1001为登录过期subscribeApiDSL — 自动分类错误处理:
repository.someCall().subscribeApi {
onSuccess { data -> /* 更新 LiveData */ }
onApiError { code, msg -> /* 提示用户 */ }
onLoginFailed { msg -> /* 跳转登录 */ }
onNetworkError { e -> /* 网络异常 */ }
disposeWith(compositeDisposable)
}# 构建 Debug APK
./gradlew assembleDebug
# 安装到设备
./gradlew installDebug
# 构建 Release APK
./gradlew assembleRelease
# 运行测试
./gradlew test
# 代码检查
./gradlew lint
# 构建单个模块
./gradlew :feature:login:assembleDebug
./gradlew :core:util:build
# 清理
./gradlew cleanWindows 环境下使用
gradlew.bat替代./gradlew。
项目使用 build-logic 约定插件统一构建配置,避免各模块重复声明 SDK 版本、公共依赖等样板代码:
| 插件 ID | 适用范围 | 说明 |
|---|---|---|
manager.application |
app 模块 |
配置 applicationId、签名、buildTypes |
manager.library |
core/*、api_xxx 模块 |
基础 Android Library 配置 |
manager.feature |
feature/* 实现模块 |
在 library 基础上增加 serialization 和 useARouter() DSL |
所有版本与依赖集中声明在 gradle/libs.versions.toml,通过 libs.* 类型安全访问器引用。
新建文件夹后创建 build.gradle.kts 文件,写入配置:
plugins {
id("manager.library") // 如果不需要serialization,只导入这个插件即可
alias(libs.plugins.kotlin.serialization)
}
android {
namespace = "com.generals.core.util" // 模块名
}
dependencies {
implementation(libs.okhttp)
implementation(libs.bundles.projectBase)
implementation(libs.arouter.api)
implementation(project(":core:base"))
}然后创建 src/main 目录,在根目录下的 settings.gradle.kts 下导入后同步即可:
include(":core:base")然后自己创建 java, res 目录即可。
与上面同理:
plugins {
id("manager.feature") // feature模块插件自动引入了serilization
}
android {
namespace = "com.generals.feature.login"
}
useARouter() // 如果需要使用Arouter,使用这个方法
dependencies {
implementation(libs.bundles.projectBase)
implementation(project(":core:base")) // 依赖的模块
implementation(project(":core:util"))
implementation(project(":core:config"))
implementation(project(":feature:login:api_login"))
}同样需要 include 到根目录的 settings.gradle.kts 下然后同步,不过需要自己创建 AndroidManifest.xml。
对于 api 模块,在目录下创建
api_xxx后创建build.gradle.kts文件:plugins { id("manager.library") } android { namespace = "com.generals.api.login" } dependencies { implementation(libs.arouter.api) }同样需要 include 到根目录的
settings.gradle.kts。
本项目基于 Apache License 2.0 开源,详见 LICENSE 文件。