Android 将有状态存储库注入WorkManager Worker
这主要是一个应用程序架构问题。 我有一个repository类,用于集中对媒体集合的操作: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
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