Не удается закрыть экземпляр Realm в ViewModel, связанный с Activity

У меня есть приложение для одного действия, и к нему прикреплен SharedViewModel, его основная цель — использовать для внутренней связи между фрагментами и т. д. Я также использую Область в качестве решения для хранения. Эта модель представления, как и другие модели представления, расширяет модель 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()!!)}"}")
    }
}

Мы все знакомы с этой картинкой Не удается закрыть экземпляр Realm в ViewModel, связанный с Activity

Поскольку жизненный цикл SharedViewModel зависит от жизненного цикла жизненного цикла активности, метод onCleared() этой модели представления будет вызываться не после onDestroy вызова активности, а по завершении активности. Это не одно и то же. В результате, когда я выхожу из своего приложения, одно соединение Realm остается открытым, потому что активность не находится в состоянии Законченный. Все другие модели просмотра, связанные из фрагментов, вызвали свои собственные методы onCleared(), и их соединения Realm закрыты.

Каков наилучший и самый чистый способ справиться с этим?

У меня есть обходной путь, в котором я вручную вызываю viewModel onCleared() в onDestroy методе активности, и он работает, но это решение — ерунда.

Заранее спасибо!

when I leave my app, one Realm connection stays open, because activity is not in the Finished state. это ошибка в вашем коде, учитывая, что onCleared() вызывается, когда вы выходите из приложения (завершаете действие).
EpicPandaForce 10.04.2019 15:23

Вы должны разделить живые данные на несколько фрагментов, используя общий ViewModel, но для ваших подключений Realm (Объекты, связанные с миром) я бы рекомендовал использовать ViewModel, который прикреплен к каждому фрагменту отдельно.

Jeel Vankhede 10.04.2019 15:26

@JeelVankhede, вы правы, но в этой модели SharedViewModel также есть некоторые живые данные, которые использует активность, а также другие фрагменты.

Draško 10.04.2019 18:25
2
3
167
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

На самом деле @EpicPandaForce был прав, ошибка была в создании ViewModel. Я использовал Кинжал 2 для инъекции ViewModelFactory, которая выглядит так:

@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)
        }
    }
}

и ViewModel, предоставленные этой фабрикой, не были привязаны к жизненному циклу какой-либо активности и фрагмента. Когда я изменил создание ViewModel как:

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

после OnDestroy() активности onCleared() позвонят.

Спасибо, парни!

Другие вопросы по теме