0

我知道如果不再需要弱引用作为强引用(例如 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。

  1. 在应用程序运行时,通过按运行 (Shift + F10) 通过 Android Studio 重新启动应用程序。该应用程序将关闭,重新启动,并且我之前有项目的 RecyclerView 现在是空白的。通过一些系统输出,我可以看到 WeakReference 有一个空引用。
  2. 在通过 FAB 将新项目添加到列表中(通过 DAO 实例处理插入)并查看我的日志时,大多数时间 WeakReference 仍在引用我的 MediatorLiveData 的 setValue() 函数,但在随机时间它将为空,但是下次我插入一个项目并重复此过程时,它不为空。

知道为什么会这样吗?如果我的 ViewModel 以及 MediatorLiveData 仍然处于活动状态并且没有被垃圾收集,那么 MediatorLiveData 的 setValue() 函数引用是否应该一直有效?

4

1 回答 1

0

当您的方法MediatorLiveData::addSource返回时,没有对您的功能接口(您想要调用的地方mMediatorLiveData::setValue)的强引用,这意味着它可以用于 GC。

从来没有对函数本身的实例变量引用,它只是一个方法参数。

只要您需要,您就应该持有对功能接口本身的引用,以便它可以调用setValue.

于 2018-02-11T00:27:59.030 回答