Android架构示例:Jetpack Compose与MVVM实践

项目标题与描述

Android Architecture Samples 是Google官方维护的架构示范项目,通过TODO应用展示多种Android开发架构模式。当前分支重点演示:

  • 采用Jetpack Compose构建的现代化UI体系
  • 符合单一Activity原则的导航架构
  • 完备的MVVM分层设计与响应式编程实现
  • 适用于生产环境的测试方案和依赖注入

功能特性

核心架构

  • 🏗️ 分层架构:清晰划分表示层(Compose+ViewModel)、领域层和数据层(Room+远程数据)
  • 🌐 响应式UI:使用Kotlin Flow实现数据驱动的界面更新
  • :puzzle_piece: 模块化设计:通过Hilt实现依赖注入,支持功能解耦

开发支持

  • :artist_palette: 双风味配置:提供mockprod产品风味,简化开发测试流程
  • :magnifying_glass_tilted_left: 完整测试套件:包含单元测试、集成测试和端到端测试
  • :high_voltage: 协程应用:全异步操作采用Kotlin协程实现

技术栈亮点

dependencies {
    implementation("androidx.compose.ui:ui")          // Jetpack Compose
    implementation("androidx.navigation:navigation-compose")  // 导航组件
    implementation("androidx.room:room-ktx")         // Room数据库
    implementation("com.google.dagger:hilt-android")  // 依赖注入
}

安装指南

环境要求

  • Android Studio Giraffe以上版本
  • JDK 17+
  • Android SDK API 34

获取代码

git clone git@github.com:android/architecture-samples.git
cd architecture-samples

构建配置

  1. 在Android Studio中打开项目根目录
  2. 选择构建风味:
    • mock:使用内存数据库的调试版本
    • prod:包含真实数据库的生产配置
  3. 执行Gradle同步

使用说明

基础功能实现

// 数据层Repository示例
class DefaultTasksRepository(
    private val tasksRemoteDataSource: TasksDataSource,
    private val tasksLocalDataSource: TasksDataSource,
    private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
) : TasksRepository {
    
    override fun getTasks(): Flow<List<Task>> {
        return tasksLocalDataSource.getTasks()
    }
}

ViewModel典型实现

class TasksViewModel(
    private val tasksRepository: TasksRepository
) : ViewModel() {

    private val _uiState = MutableStateFlow(TasksUiState())
    val uiState: StateFlow<TasksUiState> = _uiState.asStateFlow()

    fun refresh() {
        viewModelScope.launch {
            tasksRepository.refreshTasks()
            _uiState.update { it.copy(loading = false) }
        }
    }
}

Compose界面集成

@Composable
fun TasksScreen(
    viewModel: TasksViewModel = hiltViewModel(),
    onTaskClick: (Task) -> Unit
) {
    val uiState by viewModel.uiState.collectAsState()
    
    LazyColumn {
        items(uiState.tasks) { task ->
            TaskItem(task, onTaskClick)
        }
    }
}

核心代码

导航系统实现

// 导航图配置
@Composable
fun TodoNavGraph(
    navController: NavHostController = rememberNavController()
) {
    NavHost(
        navController = navController,
        startDestination = Screen.Tasks.route
    ) {
        composable(Screen.Tasks.route) {
            TasksScreen { task ->
                navController.navigate("${Screen.TaskDetail.route}/${task.id}") 
            }
        }
        composable(
            route = "${Screen.TaskDetail.route}/{taskId}",
            arguments = listOf(navArgument("taskId") { type = NavType.StringType })
        ) { backStackEntry ->
            val taskId = backStackEntry.arguments?.getString("taskId")!!
            TaskDetailScreen(taskId = taskId)
        }
    }
}

数据库访问层

// Room数据库定义
@Database(entities = [Task::class], version = 1)
@TypeConverters(Converters::class)
abstract class ToDoDatabase : RoomDatabase() {
    abstract fun taskDao(): TasksDao
}

// DAO接口
@Dao
interface TasksDao {
    @Query("SELECT * FROM tasks")
    fun observeTasks(): Flow<List<Task>>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertTask(task: Task)
}

测试方案示例

// ViewModel测试
@HiltAndroidTest
class TasksViewModelTest {
    
    @get:Rule
    val hiltRule = HiltAndroidRule(this)

    @Inject
    lateinit var repository: FakeTestRepository

    @Before
    fun setup() {
        hiltRule.inject()
    }

    @Test
    fun loadingTasks_emitsSuccessUiState() = runTest {
        val viewModel = TasksViewModel(repository)
        viewModel.refresh()
        
        val state = viewModel.uiState.first()
        assertEquals(3, state.tasks.size) 
    }
}

更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)
公众号二维码

posted @ 2025-07-07 22:01  qife  阅读(41)  评论(0)    收藏  举报