Android 将有状态存储库注入WorkManager Worker

Android 将有状态存储库注入WorkManager Worker,android,dagger-2,kotlin-coroutines,android-workmanager,Android,Dagger 2,Kotlin Coroutines,Android Workmanager,这主要是一个应用程序架构问题。 我有一个repository类,用于集中对媒体集合的操作: interface MediaRepository { suspend fun getTracks(): List<Track> suspend fun getAlbums(): List<Album> fun observeMediaChanges(): Flow<ChangeNotification> } 因此,MediaRepositor

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

interface MediaRepository {
    suspend fun getTracks(): List<Track>
    suspend fun getAlbums(): List<Album>
    fun observeMediaChanges(): Flow<ChangeNotification>
}
因此,
MediaRepository
的实现是有状态的:它从第一次调用等价的
getX
函数起,就懒散地观察
流的变化,在收到时缓存最新接收的值,然后计算并向
observeMediaChanges()
的观察者广播
更改通知

存储库
仅注入到
服务
中时,此结构运行良好,因为当服务终止时可以清理存储库资源。我现在需要将相同的
MediaRepository
注入到
Worker
的实例中。因为工作人员有自己的生命周期,所以我需要将
MediaRepository
作为一个单例

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

我的想法
  • MediaRepository
    设为无状态,并将媒体列表显示为
    Flow
    s。然后,消费者有责任缓存最新的值
  • 将缓存保留在
    MediaRepository
    中,但不要在服务和工作程序之间共享实例
  • 根本不要使用缓存,因为大多数数据都是从设备的存储器中读取的

  • 我想您已经声明了匕首组件

    您只能将提供的MediaRepository实现标记为@Singleton

    @Singleton
    class MediaRepositoryImpl @Inject constructor(...)
    
    在模块中,将该实例绑定到其接口

    @Binds fun bindsMediaRepository(impl: MediaRepositoryImpl): MediaRepository
    
    若要为工作者提供其他参数,必须在应用程序中实例化自定义WorkManagerFactory

    一步一步地非常详细地解释整个过程


    还可以查看一下

    您的存储库不应该是有状态的。解决了的!我已经考虑过了。那么在这种情况下,我应该在哪里引入缓存层呢?因为缓存总是有状态的,谢谢你的回答。我对如何建立这些工厂有一个相当精确的想法。我所面临的问题是,将存储库作为一个单例公开具有很高的内存泄漏风险,因为它是有状态的。我正在寻找一种构造我的应用程序的方法来避免这种情况,正如EpicPandaForce指出的,这不应该是
    @Singleton
    。无论如何,如果您被迫这样做,您可以重用当前创建的实例,将其标记为
    @reusible
    ,这样,如果任何使用者不再指向该实例,dagger将释放该实例。
    @Binds fun bindsMediaRepository(impl: MediaRepositoryImpl): MediaRepository