价格

项目总览

相关源文件

本页面内容基于以下源文件生成:

项目背景与简介

本项目是一个基于 Jetpack Compose 构建的 WanAndroid 客户端应用,旨在通过实战项目展示现代 Android 声明式 UI 开发范式。项目采用 MVI(Model-View-Intent) 架构模式,结合 单 Activity 架构设计,实现了应用内多页面的统一管理与状态流转。

项目核心价值在于探索 Compose 1.0 稳定版本在生产环境中的应用实践。通过将前端框架(如 React)的单向数据流思想引入 Android 开发,项目构建了一个状态可预测、逻辑高度解耦的客户端应用。这不仅降低了 UI 状态管理的复杂度,也为后续功能迭代提供了清晰的代码结构基础。

在功能实现上,项目完整复刻了 WanAndroid 平台的核心业务流程,包括用户登录、首页文章流、体系分类、项目展示及我的个人中心等模块。通过声明式 UI 的特性,界面能够实时响应数据变化,提供流畅的用户体验。

技术栈与依赖配置

项目采用 Kotlin 作为主要开发语言,全面拥抱 Jetpack Compose 生态。核心依赖配置围绕声明式 UI、依赖注入、网络请求及异步数据处理展开。

核心技术栈

技术分类技术选型版本/说明
UI 框架Jetpack Compose1.0 稳定版,声明式 UI 工具包
架构模式MVI单向数据流架构,强调唯一数据源
依赖注入HiltGoogle 官方推荐的 DI 框架
网络请求Retrofit + OkHttpRESTful API 请求库
异步处理Kotlin Coroutines & Flow协程与响应式流
图片加载Accompanist Coil/GlideCompose 专用图片加载库
分页加载Paging 3流式分页数据加载
本地存储DataStore替代 SharedPreferences 的现代存储方案

构建配置与依赖管理

项目在 app/build.gradle 中进行了详细的构建配置。编译 SDK 版本设置为 31,最低支持 SDK 21,目标 SDK 为 31,确保覆盖绝大多数主流设备 (app/build.gradle:11-24)。

在构建特性方面,启用了 compose true 以支持 Compose 编译器插件,并配置了 Kotlin 编译选项以启用 IR 编译器后端 (app/build.gradle:40-46)。

依赖库的选择体现了“Compose First”的原则:

  1. UI 基础:引入了 compose.uicompose.materialcompose.ui-tooling-preview,提供基础的 UI 组件和预览支持 (app/build.gradle:59-61)。
  2. 导航与动画:使用 navigation-compose 实现页面路由,配合 accompanist 系列库(如 accompanist-pager, accompanist-swiperefresh)补充了 Compose 暂时缺失的常用控件能力 (app/build.gradle:69-86)。
  3. 架构组件:集成 hilt-android 及其 Compose 扩展,实现 ViewModel 的自动注入和依赖管理 (app/build.gradle:88-93)。
  4. 数据层:使用 Retrofit 处理网络请求,Gson 进行 JSON 解析,Paging 处理列表分页,Datastore 处理数据持久化(如 Cookie) (app/build.gradle:95-108)。

应用配置与入口

应用遵循单 Activity 架构,MainActivity 作为应用的唯一入口,承载了所有的 Compose 页面容器。

应用清单配置

AndroidManifest.xml 中,应用声明了必要的网络权限(INTERNETACCESS_NETWORK_STATE)以支持 API 调用 (app/src/main/AndroidManifest.xml:5-6)。

应用类指定为 .MyApp,这通常是初始化 Hilt 依赖注入容器和全局配置的起点 (app/src/main/AndroidManifest.xml:14)。MainActivity 被配置为 LAUNCHER Activity,并使用了 SplashTheme 作为启动主题,以优化应用启动时的视觉体验 (app/src/main/AndroidManifest.xml:16-26)。

应用标识与版本

应用的包名为 com.zj.wanandroid,版本号定义为 1.0 (app/build.gradle:14-18)。这种配置符合标准 Android 应用发布规范,确保应用在设备上的唯一性和可更新性。

架构设计概览

本项目采用 MVI (Model-View-Intent) 架构模式,这是一种受 Redux 启发的单向数据流架构。与传统的 MVVM 相比,MVI 更加强调状态的不可变性和数据流向的唯一性,这与 Compose 的声明式 UI 理念高度契合。

MVI 架构分层

MVI 架构将应用分为三个核心层次,各层职责明确:

  1. Model (UI State): 不同于 MVVM 中的数据层,MVI 的 Model 主要指 UI 状态。它是一个不可变的数据类,包含了页面渲染所需的所有信息(如加载状态、数据内容、焦点状态等)。
  2. View: 负责 UI 渲染与用户交互。在 Compose 中,这通常由 @Composable 函数实现。View 不直接修改状态,而是通过订阅 Model 的变化来重组界面。
  3. Intent: 代表用户的操作意图(如点击、输入)。View 将用户操作封装成 Intent 发发给处理层。

核心数据结构定义

为了实现严格的 MVI 模式,项目定义了三种核心数据结构来约束数据流向。以登录页面为例 (README.md:25-54):

  • ViewState: 定义页面的所有状态。

    kotlin
    1data class LoginViewState(
    2    val account: String = "",
    3    val password: String = "",
    4    val isLogged: Boolean = false
    5)
    • 职责: 集中管理页面状态,确保 View 只需订阅一个数据源即可获取所有 UI 信息。
    • 关键点: 字段默认值确保了状态的初始安全性。
  • ViewEvent: 定义一次性事件。

    kotlin
    1sealed class LoginViewEvent {
    2    object PopBack : LoginViewEvent()
    3    data class ErrorMessage(val message: String) : LoginViewEvent()
    4}
    • 职责: 处理非状态类的副作用,如 Toast 提示、页面跳转、弹窗关闭等。
    • 关键点: 使用 sealed class 限制事件类型,防止事件泛滥。
  • ViewAction (Intent): 定义用户操作。

    kotlin
    1sealed class LoginViewAction {
    2    object Login : LoginViewAction()
    3    data class UpdateAccount(val account: String) : LoginViewAction()
    4    // ...
    5}
    • 职责: 将用户的所有交互行为标准化。
    • 关键点: View 层只发出 Action,不直接处理业务逻辑。

MVI 与 MVVM 的对比

MVI 架构在 MVVM 基础上进行了改良,主要区别在于 (README.md:60-67):

  1. 交互方式约束: MVVM 中 View 可以随意调用 ViewModel 的方法,而 MVI 禁止 View 直接调用 ViewModel 方法,只能通过发送 Intent 驱动状态变化。这使得业务逻辑的触发点更加清晰。
  2. 状态管理: MVVM 的 ViewModel 中通常包含多个 LiveData/StateFlow,而 MVI 使用唯一的 ViewState 容器集中管理状态。这减少了模板代码,并避免了状态不一致的问题。

系统架构与数据流

系统模块架构图

下图展示了项目的宏观模块划分及其依赖关系。系统自下而上分为数据层、领域层(业务逻辑)、架构层(MVI 协调)和表现层。

正在加载图表渲染器...

架构图说明:

  1. 单向数据流: 数据从 Repository 经过 ViewModel 处理后流向 View,View 仅通过 Intent 发送用户操作,不直接修改数据。
  2. 依赖注入: Hilt 贯穿全局,负责管理 ViewModel、Repository 及其依赖的创建与生命周期。
  3. 职责分离: Repository 负责协调远程(API)和本地(DataStore)数据源,对上层屏蔽数据获取细节。

关键交互流程

下图展示了用户在登录场景下的核心交互时序,体现了 MVI 架构如何处理用户输入并更新 UI。

正在加载图表渲染器...

交互流程说明:

  1. 输入处理: 用户的每一次输入都被封装为 Intent 发送给 ViewModel,确保了状态变更的可追溯性。
  2. 状态驱动 UI: ViewModel 接收到 Intent 后,更新内部的 ViewState,新的状态自动推送到 View 触发重组。
  3. 副作用处理: 对于登录成功后的跳转或失败的 Toast,通过 ViewEvent 单独处理,避免状态重绘导致的副作用重复触发。

核心模块与实现细节

1. 表现层

表现层由 MainActivity 和各个页面的 Composable 函数组成。MainActivity 作为单 Activity 架构的容器,主要负责初始化 NavHost 和主题配置。

  • 职责: 渲染 UI、捕获用户操作、订阅状态。
  • 关键实现: 使用 NavHost 管理路由图,每个目标对应一个 Composable 页面。页面内部通过 viewModel() 函数获取 Hilt 注入的 ViewModel 实例,并通过 collectAsState() 将 Flow 转换为 Compose 的 State 对象。
  • 证据: MainActivity 在 Manifest 中被声明为 LAUNCHER (app/src/main/AndroidManifest.xml:16-26)。

2. MVI 协调层

ViewModel 是 MVI 架构的协调中心,负责处理 Intent 并产生新的 ViewState。

  • 职责: 接收 View 层的 Intent、调用 UseCase 执行业务逻辑、将结果映射为 ViewState、处理 ViewEvent。
  • 关键数据流: Intent -> ViewModel -> UseCase -> Repository -> Result -> ViewState
  • 状态管理: 使用 StateFlowLiveData 持有 ViewState。对于一次性事件,通常使用 SharedFlow 或在 Channel 中发送。
  • 证据: README 中详细定义了 LoginViewStateLoginViewAction 的结构 (README.md:30-53)。

3. 数据层

数据层负责数据的获取与持久化,通过 Repository 模式统一数据源。

  • 职责: 提供纯净的数据给上层,屏蔽数据来源(网络或缓存)。
  • 网络请求: 使用 Retrofit 定义 API 接口,结合 Gson 进行序列化。
  • 本地存储: 使用 Datastore 存储用户登录凭证(Cookie)等键值对数据。
  • 证据: build.gradle 中引入了 retrofit, gson, datastore-preferences 等依赖 (app/build.gradle:96-102)。

4. 依赖注入层

使用 Hilt 框架管理应用的所有依赖关系。

  • 职责: 自动提供 ViewModel、Repository、NetworkClient 等实例,管理其生命周期。
  • 关键模块:
    • AppModule: 提供 Retrofit、OkHttp 等单例。
    • ViewModelModule: 定义 ViewModel 的注入键。
  • 集成: 通过 @HiltAndroidApp 注解初始化 Application,@AndroidEntryPoint 注解标记 Activity。
  • 证据: build.gradle 中应用了 dagger.hilt.android.plugin 插件 (app/build.gradle:6),并引入了相关依赖库 (app/build.gradle:88-93)。

报告阅读路线图

为了帮助开发者快速理解项目全貌,建议按照以下顺序阅读本技术分析报告:

正在加载图表渲染器...

阅读建议:

  1. 架构先行: 首先理解 MVI 架构的分层逻辑,这是理解代码组织方式的关键。
  2. UI 与数据分离: 分别研究 Compose 的 UI 构建方式和 Repository 的数据获取方式,最后再看它们如何在 ViewModel 中结合。
  3. 关注细节: 在理解整体流程后,深入 Accompanist 库的使用和 Paging 分页逻辑,这些是提升用户体验的关键技术点。