Draško
Draško

Reputation: 2221

Can not close Realm instance in ViewModel connected with Activity

I have single activity app and I have SharedViewModel attached to it, its main purpose is to be used for inner communication between fragments, etc. I also use Realm as storage solution. This viewModel as well as the others viewModels extends BaseViewModel.

open class BaseViewModel(): ViewModel() {

    val  realm: Realm = Realm.getDefaultInstance()

    override fun onCleared() {
        super.onCleared()
        realm.close()
        Log.d("BVM", "realm is ${ if (realm.isClosed) "closed." else "not closed.  Opened connections: ${Realm.getLocalInstanceCount(Realm.getDefaultConfiguration()!!)}"}")
    }
}

We are all familiar with this picture enter image description here

Since SharedViewModel's lyfecycle depends on lifecycle of activity's lifecycle, onCleared() method of this viewModel will be called not after onDestroy call of activity, but when activity is finished. It is not the same thing. As a result of that, when I leave my app, one Realm connection stays open, because activity is not in the Finished state. All other viewmodels connected from fragments had called their own onCleared() methods and their Realm's connections are closed.

What is the best and cleanest way to handle this?

I have a workaround in which I call viewModel's onCleared() manually in onDestroy method of activity and it's working, but that solution is rubbish.

Thanks in advance!

Upvotes: 2

Views: 227

Answers (1)

Draško
Draško

Reputation: 2221

As a matter of fact, @EpicPandaForce was right, the bug was in ViewModel's creation. I used Dagger 2 for injection of ViewModelFactory which looks like this:

@Singleton
class ViewModelFactory @Inject constructor(
        private val creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>
) : ViewModelProvider.Factory {
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        val creator = creators[modelClass] ?: creators.entries.firstOrNull {
            modelClass.isAssignableFrom(it.key)
        }?.value ?: throw IllegalArgumentException("unknown model class $modelClass")
        try {
            @Suppress("UNCHECKED_CAST")
            return creator.get() as T
        } catch (e: Exception) {
            throw RuntimeException(e)
        }
    }
}

and ViewModels provided by this factory were not bound to lifecycle of any activity and fragment. When I changed the creation of ViewModel as:

sharedViewModel = ViewModelProviders.of(this).get(SharedViewModel::class.java)

after OnDestroy() of activity, onCleared() get called.

Thanks, guys!

Upvotes: 1

Related Questions