弱引用函数类型参数空行为
WeakReference to function type parameter null behavior
我知道如果不再需要弱引用作为强引用(例如 Activity 被销毁或 ViewModel 被清理),垃圾收集器将允许垃圾收集器清理它的引用。但是我试图理解这样一种情况,即当函数的所属实例尚未被垃圾回收时,我对函数的 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() returns null.
- 当应用程序处于 运行 时,按 运行 (Shift + F10) 通过 Android Studio 重新启动应用程序。该应用程序将关闭,重新启动,之前有项目的我的 RecyclerView 现在是空白的。通过一些系统输出,我可以看到 WeakReference 有一个空引用。
- 在通过 FAB(通过 DAO 实例处理插入)向列表添加新项目并查看我的日志时,大多数时候 WeakReference 仍在引用我的 MediatorLiveData 的 setValue() 函数,但在随机时间它将是空的,但下次我插入一个项目并且重复这个过程时它不是空的。
知道为什么会这样吗?如果我的 ViewModel 和 MediatorLiveData 仍然处于活动状态并且没有被垃圾收集,那么 MediatorLiveData 的 setValue() 函数引用不应该一直有效吗?
当您的方法 MediatorLiveData::addSource
returns 时,没有对您的功能接口(您要调用的地方 mMediatorLiveData::setValue
)的强引用,这意味着它由 GC 决定。
从来没有对函数本身的实例变量引用,它只有一个方法参数。
您应该保留对功能接口本身的引用,只要您需要它,这样它就可以调用 setValue
。
我知道如果不再需要弱引用作为强引用(例如 Activity 被销毁或 ViewModel 被清理),垃圾收集器将允许垃圾收集器清理它的引用。但是我试图理解这样一种情况,即当函数的所属实例尚未被垃圾回收时,我对函数的 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() returns null.
- 当应用程序处于 运行 时,按 运行 (Shift + F10) 通过 Android Studio 重新启动应用程序。该应用程序将关闭,重新启动,之前有项目的我的 RecyclerView 现在是空白的。通过一些系统输出,我可以看到 WeakReference 有一个空引用。
- 在通过 FAB(通过 DAO 实例处理插入)向列表添加新项目并查看我的日志时,大多数时候 WeakReference 仍在引用我的 MediatorLiveData 的 setValue() 函数,但在随机时间它将是空的,但下次我插入一个项目并且重复这个过程时它不是空的。
知道为什么会这样吗?如果我的 ViewModel 和 MediatorLiveData 仍然处于活动状态并且没有被垃圾收集,那么 MediatorLiveData 的 setValue() 函数引用不应该一直有效吗?
当您的方法 MediatorLiveData::addSource
returns 时,没有对您的功能接口(您要调用的地方 mMediatorLiveData::setValue
)的强引用,这意味着它由 GC 决定。
从来没有对函数本身的实例变量引用,它只有一个方法参数。
您应该保留对功能接口本身的引用,只要您需要它,这样它就可以调用 setValue
。