Reputation: 2310
I understand that a WeakReference will allow the garbage collector to clean up its reference if it is no longer needed as a strong reference (such as an Activity being destroyed or ViewModel being cleaned up). But I'm trying to understand a case where my WeakReference to a function is returning a null reference at random points when the function's owning instance hasn't been garbage collected...
Consider the following 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())
})
...
}
I pass the results of the original LiveData for further processing to an AsyncTask as well as a function type reference to setValue so the AsyncTask can call the mediator's setValue() in onPostExecute().
Consider the following 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)
}
I would think so long as onCleared() hasn't been called on the ViewModel, and it hasn't been garbage collected, that the WeakReference will always contain a non-null reference. But it so happens that there are two cases I've seen where mOnFinishCallback.get() returns null.
Any idea why this might be? If my ViewModel, and thus MediatorLiveData are still active and not being garbage collected, shouldn't the MediatorLiveData's setValue() function reference be valid the whole time?
Upvotes: 0
Views: 1105
Reputation: 9929
When your method MediatorLiveData::addSource
returns then there is no strong reference to you're functional interface (where you want to invoke mMediatorLiveData::setValue
) meaning it is up for GC.
There is never an instance variable reference to the function itself, its only a method parameter.
You should hold a reference to the functional interface itself, for as long as you need it, so it can invoke setValue
.
Upvotes: 0