首页 > 解决方案 > 将有状态存储库注入 WorkManager Worker

问题描述

这主要是一个应用程序架构问题。我有一个存储库类,用于集中对媒体集合的操作:

interface MediaRepository {
    suspend fun getTracks(): List<Track>
    suspend fun getAlbums(): List<Album>
    fun observeMediaChanges(): Flow<ChangeNotification>
}

该存储库从多个 DAO 源中提取数据,这些源公开其数据Flow以观察如下变化:

interface MediaDao {
    fun getTracks(): Flow<List<Track>>
    fun getAlbums(): Flow<List<Album>>
}

因此, 的实现是有状态的:它从第一次调用等效函数时MediaRepository就懒惰地观察 s 的变化,每当收到时缓存最新接收到的值,然后计算并将 a 广播给 的观察者。FlowgetXChangeNotificationobserveMediaChanges()

这种结构在Repository仅注入 a时运行良好Service,因为在服务终止时可以清理存储库资源。我现在需要将相同MediaRepository的注入到Worker. 由于工人有自己的生命周期,我需要做MediaRepository一个单例。

问题

通过在应用程序的整个生命周期中保持活动订阅,我是否会泄漏有价值的资源(例如,一个 DAO 内部使用ContentObservers)?如何更改我的应用架构以避免泄漏?

我想到了什么

  1. 使MediaRepository无状态并将媒体列表公开为Flows。然后,消费者有责任缓存最新的值。
  2. 将缓存保留在 中MediaRepository,但不要在服务和工作人员之间共享实例。
  3. 根本不要使用缓存,因为大多数数据都是从设备的存储中读取的。

标签: androiddagger-2kotlin-coroutinesandroid-workmanager

解决方案


我想你已经声明了一个匕首组件。

您只需使用 @Singleton 标记提供的 MediaRepository 实现。

@Singleton
class MediaRepositoryImpl @Inject constructor(...)

并在模块中将此实例绑定到其接口

@Binds fun bindsMediaRepository(impl: MediaRepositoryImpl): MediaRepository

要为 Worker 提供其他参数,您必须在应用程序中实例化自定义 WorkManagerFactory。

这篇中等帖子非常详细地逐步解释了整个过程。

也可以看看官方文档


推荐阅读