You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何结合Coroutines与Flow实现Room Database的Repository及ViewModel?

集成Coroutines与Flow重构Room的Repository和ViewModel

Repository绝对不是多余的——它是解耦UI层和数据层的核心角色,负责统一管理本地(Room)和可能的远程数据源,让代码更易维护和测试。下面一步步教你集成Coroutines与Flow来重构,全程不用Hilt,聚焦核心逻辑:

1. DAO层:用Flow实现数据自动监听

Room原生支持Flow,DAO的查询方法直接返回Flow<数据类型>即可,Room会自动在后台线程执行查询,且数据变化时自动推送给下游。

先定义实体类:

@Entity(tableName = "users")
data class User(
    @PrimaryKey val id: Int,
    val name: String,
    val email: String
)

然后写DAO接口:

@Dao
interface UserDao {
    // 查询所有用户,返回Flow,Room自动后台执行+数据变化通知
    @Query("SELECT * FROM users")
    fun getAllUsers(): Flow<List<User>>

    // 增删改加suspend修饰,必须在Coroutine中调用(Room已默认处理线程切换)
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertUser(user: User)

    @Delete
    suspend fun deleteUser(user: User)
}

2. Repository层:封装数据源,暴露Flow给ViewModel

Repository持有DAO实例,封装所有数据操作逻辑,ViewModel只和它交互,不用关心数据来自本地还是远程。

class UserRepository(private val userDao: UserDao) {
    // 直接暴露DAO的Flow,ViewModel可以直接监听
    val allUsers: Flow<List<User>> = userDao.getAllUsers()

    // 封装插入操作,有需要的话这里可以加远程请求逻辑(比如先调API再存本地)
    suspend fun insertUser(user: User) {
        userDao.insertUser(user)
    }

    suspend fun deleteUser(user: User) {
        userDao.deleteUser(user)
    }
}

3. ViewModel层:用ViewModelScope管理Coroutine,安全收集Flow

ViewModel用自带的viewModelScope启动Coroutine(自动在ViewModel销毁时取消,避免内存泄漏),用repeatOnLifecycle确保只在UI可见时收集Flow。

先添加必要的依赖(直接复制到build.gradle):

// Lifecycle库,用于处理生命周期安全的Flow收集
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.6.2"

然后写ViewModel代码:

class UserViewModel(private val repository: UserRepository) : ViewModel() {
    // 用StateFlow暴露给UI(比LiveData更贴合Flow生态)
    private val _users = MutableStateFlow<List<User>>(emptyList())
    val users: StateFlow<List<User>> = _users

    init {
        // 监听Repository的Flow,更新StateFlow
        viewModelScope.launch {
            // 仅在UI处于STARTED状态时收集,STOPPED时自动取消
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                repository.allUsers.collect { userList ->
                    _users.value = userList
                }
            }
        }
    }

    // 处理UI触发的插入事件
    fun insertUser(user: User) {
        viewModelScope.launch {
            repository.insertUser(user)
        }
    }

    // 处理UI触发的删除事件
    fun deleteUser(user: User) {
        viewModelScope.launch {
            repository.deleteUser(user)
        }
    }
}

4. UI层:安全收集Flow(两种场景示例)

Jetpack Compose场景

@Composable
fun UserScreen(viewModel: UserViewModel = viewModel()) {
    // 自动处理生命周期的Flow收集
    val users by viewModel.users.collectAsStateWithLifecycle()

    LazyColumn {
        items(users) { user ->
            UserItem(user, onDeleteClick = { viewModel.deleteUser(user) })
        }
    }

    Button(onClick = {
        viewModel.insertUser(User(1, "测试用户", "test@example.com"))
    }) {
        Text("添加用户")
    }
}

传统View(Activity/Fragment)场景

class UserActivity : AppCompatActivity() {
    private lateinit var viewModel: UserViewModel
    private lateinit var adapter: UserAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_user)

        adapter = UserAdapter()
        rv_users.adapter = adapter

        viewModel = ViewModelProvider(this)[UserViewModel::class.java]

        // 生命周期安全的Flow收集
        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                viewModel.users.collect { userList ->
                    adapter.submitList(userList)
                }
            }
        }

        btn_add.setOnClickListener {
            viewModel.insertUser(User(1, "测试用户", "test@example.com"))
        }
    }
}

核心要点总结

  1. Repository是必要的:解耦UI与数据层,封装多数据源逻辑,方便单元测试。
  2. Room+Flow:DAO返回Flow实现数据自动监听,无需手动轮询数据库。
  3. Coroutines:用suspend修饰耗时操作,配合viewModelScope/lifecycleScope管理生命周期,避免内存泄漏。
  4. 生命周期安全:用repeatOnLifecycle和collectAsStateWithLifecycle确保Flow只在UI可见时收集,节省系统资源。

内容的提问来源于stack exchange,提问作者Sqa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 23:06:34