【发布时间】:2018-07-21 10:26:53
【问题描述】:
我了解,如果不再需要将 WeakReference 作为强引用(例如销毁 Activity 或清理 ViewModel),WeakReference 将允许垃圾收集器清理其引用。但是我试图理解这样一种情况,即当函数拥有的实例尚未被垃圾收集时,我对函数的 WeakReference 在随机点返回空引用...
考虑以下 ViewModel:
class SampleVM(dao: MyRoomDao) : ViewModel() {
private val mLiveData: LiveData<List<Object>> = dao.loadAll()
private val mMediatorLiveData: MediatorLiveData<List<Object>> = MediatorLiveData()
init {
mMediatorLiveData.addSource(mLiveData, { dbResult ->
MyAsyncTask(
mMediatorLiveData::setValue
).execute(dbResult ?: ArrayList())
})
...
}
我将原始 LiveData 的结果传递给 AsyncTask 以供进一步处理,并将 function type reference 传递给 setValue,以便 AsyncTask 可以在 onPostExecute() 中调用中介的 setValue()。
考虑以下 AsyncTask:
class MyAsyncTask(onFinishCallback: (List<Object>) -> Unit) : AsyncTask<...,...,...>() {
private val mOnFinishCallback = WeakReference<(List<Object>) -> Unit>(onFinishCallback)
...(overrides)...
override fun onPostExecute(result: List<Object>?) {
result?.let {
mOnFinishCallback.get()?.invoke(it)
}
我认为只要未在 ViewModel 上调用 onCleared() 并且未对它进行垃圾回收,WeakReference 将始终包含非空引用。但碰巧我见过两种情况 mOnFinishCallback.get() 返回 null。
- 在应用程序运行时,通过 Android Studio 按运行 (Shift + F10) 重新启动应用程序。该应用程序将关闭,重新启动,并且我之前有项目的 RecyclerView 现在是空白的。通过一些系统输出,我可以看到 WeakReference 有一个空引用。
- 在通过 FAB 向列表添加新项目(通过 DAO 实例处理插入)并查看我的日志时,大部分时间 WeakReference 仍在引用我的 MediatorLiveData 的 setValue() 函数,但它会在随机时间null,但下次我插入一个项目并重复此过程时,它不为 null。
知道为什么会这样吗?如果我的 ViewModel 以及 MediatorLiveData 仍然处于活动状态并且没有被垃圾收集,那么 MediatorLiveData 的 setValue() 函数引用是否应该一直有效?
【问题讨论】:
-
当然,一旦
.addSource方法返回,那么就没有对你的功能接口(你想在其中调用mMediatorLiveData::setValue)的强引用,这意味着它是由 GC 决定的——从来没有实例变量引用函数本身,它只是一个方法参数。 ? -
也可能是功能界面上
inline和noinline的区别。 -
就是这样。在 ViewModel 中,我创建了如下引用: private val mCallback = mMediatorLiveData::setValue 并将其传递给 AsyncTask 的构造函数。随意写一个答案,我会将其标记为已接受。
-
很高兴解决了!
标签: android kotlin weak-references android-livedata android-viewmodel