我知道如果不再需要弱引用作为强引用(例如 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 以供进一步处理,并将函数类型引用传递给 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。
- 在应用程序运行时,通过按运行 (Shift + F10) 通过 Android Studio 重新启动应用程序。该应用程序将关闭,重新启动,并且我之前有项目的 RecyclerView 现在是空白的。通过一些系统输出,我可以看到 WeakReference 有一个空引用。
- 在通过 FAB 将新项目添加到列表中(通过 DAO 实例处理插入)并查看我的日志时,大多数时间 WeakReference 仍在引用我的 MediatorLiveData 的 setValue() 函数,但在随机时间它将为空,但是下次我插入一个项目并重复此过程时,它不为空。
知道为什么会这样吗?如果我的 ViewModel 以及 MediatorLiveData 仍然处于活动状态并且没有被垃圾收集,那么 MediatorLiveData 的 setValue() 函数引用是否应该一直有效?