rOO*_*b85 1 android leakcanary android-room android-viewmodel
LeakCanary 告诉我,我的一个 ViewModel 正在泄漏,但在玩了 2 天后,我无法让泄漏消失。
这是获取 ViewModel 的 Fragment
viewModel = ViewModelProvider(this).get(ViewBreederViewModel::class.java).apply {
getStrains(arguments?.getString(BREEDER_ID_KEY, "")!!)
}
Run Code Online (Sandbox Code Playgroud)
这是视图模型
class ViewBreederViewModel(application: Application) : AndroidViewModel(application) {
private val breederRepository = BreederRepository(application)
val strainList = MutableLiveData<List<MinimalStrain>>()
fun getStrains(breederId: String) {
viewModelScope.launch {
breederRepository.getMinimalStrains(breederId).observeForever {
strainList.value = it
}
}
}
Run Code Online (Sandbox Code Playgroud)
}
这是 BreederRepository:
class BreederRepository(context: Context) {
private val dao: BreederDao
private val breederApi = RetrofitClientInstance.getInstance(context).breederAndStrainIdsApi
init {
val database: Db = Db.getInstance(
context
)!!
dao = database.breederDao()
}
suspend fun getMinimalStrains(breederId: String): LiveData<List<MinimalStrain>> =
withContext(Dispatchers.IO) {
dao.getMinimalStrains(breederId)
}
Run Code Online (Sandbox Code Playgroud)
}
这是 Db 类
@Database(
entities = [Breeder::class, Strain::class],
version = 1,
exportSchema = true)
@TypeConverters(RoomDateConverter::class)
abstract class Db : RoomDatabase() {
abstract fun breederDao(): BreederDao
companion object {
private var instance: Db? = null
@JvmStatic
fun getInstance(context: Context): Db? {
if (instance == null) {
synchronized(Db::class) {
instance = Room.databaseBuilder(
context.applicationContext,
Db::class.java, "seedfinder_db"
)
.build()
}
}
return instance
}
}
Run Code Online (Sandbox Code Playgroud)
}
您正在使用observeForever
,顾名思义,它将永远持续观察,即使在您的 ViewModel 被清除之后也是如此。Room 不需要使用suspend
返回 a 的 DAO 方法LiveData
,而且在任何情况下这都不是正确的方法 -LiveData
已经是异步的。
相反,您应该转换您的 LiveData,使用您breederId
作为 LiveData 的输入strainList
:
class ViewBreederViewModel(application: Application) : AndroidViewModel(application) {
private val breederRepository = BreederRepository(application)
private val currentBreederId = MutableLiveData<String>()
// Here we use the switchMap method from the lifecycle-livedata-ktx artifact
val strainList: LiveData<String> = currentBreederId.switchMap {
breederId -> breederRepository.getMinimalStrains(breederId)
}
private fun setBreederId(breederId: String) {
currentBreederId.value = breederId
}
}
Run Code Online (Sandbox Code Playgroud)
你将getMinimalStrains
成为:
fun getMinimalStrains(breederId: String): LiveData<List<MinimalStrain>> =
dao.getMinimalStrains(breederId)
Run Code Online (Sandbox Code Playgroud)
breederId
您可以通过在 UI 中设置并strainList
像以前一样观察您来使用它:
viewModel = ViewModelProvider(this).get(ViewBreederViewModel::class.java).apply {
setBreederId(arguments?.getString(BREEDER_ID_KEY, "")!!)
}
viewModel.strainList.observe(viewLifecycleOwner) { strainList ->
// use your updated list
}
Run Code Online (Sandbox Code Playgroud)
如果您正在使用ViewModel 的 Saved State 模块(如果您使用的是最新的稳定片段/活动库,则这是默认的),那么您可以使用SavedStateHandle
,它会从片段的参数中自动填充并完全跳过setBreederId()
:
class ViewBreederViewModel(
application: Application,
savedStateHandle: SavedStateHandle
) : AndroidViewModel(application) {
private val breederRepository = BreederRepository(application)
// Here we use the switchMap method from the lifecycle-livedata-ktx artifact
val strainList: LiveData<String> = savedStateHandle
.getLiveData(BREEDER_ID_KEY) // Automatically populated from arguments
.switchMap {
breederId -> breederRepository.getMinimalStrains(breederId)
}
}
Run Code Online (Sandbox Code Playgroud)
这意味着您的代码可以简单地变成:
viewModel = ViewModelProvider(this).get(ViewBreederViewModel::class.java)
viewModel.strainList.observe(viewLifecycleOwner) { strainList ->
// use your updated list
}
Run Code Online (Sandbox Code Playgroud)
如果您使用该fragment-ktx
工件,您可以进一步简化为:
// Move this to where you declare viewModel
val viewModel: ViewBreederViewModel by viewModels()
viewModel.strainList.observe(viewLifecycleOwner) { strainList ->
// use your updated list
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1643 次 |
最近记录: |