Как уже указывалось, невозможно очистить отдельную ViewModel от ViewModelStore с помощью API компонентов архитектуры.Одним из возможных решений этой проблемы является наличие хранилищ для каждой модели ViewModel, которые при необходимости можно безопасно очистить:
class MainActivity : AppCompatActivity() {
val individualModelStores = HashMap<KClass<out ViewModel>, ViewModelStore>()
inline fun <reified VIEWMODEL : ViewModel> getSharedViewModel(): VIEWMODEL {
val factory = object : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
//Put your existing ViewModel instantiation code here,
//e.g., dependency injection or a factory you're using
//For the simplicity of example let's assume
//that your ViewModel doesn't take any arguments
return modelClass.newInstance()
}
}
val viewModelStore = this@MainActivity.getIndividualViewModelStore<VIEWMODEL>()
return ViewModelProvider(this.getIndividualViewModelStore<VIEWMODEL>(), factory).get(VIEWMODEL::class.java)
}
val viewModelStore = this@MainActivity.getIndividualViewModelStore<VIEWMODEL>()
return ViewModelProvider(this.getIndividualViewModelStore<VIEWMODEL>(), factory).get(VIEWMODEL::class.java)
}
inline fun <reified VIEWMODEL : ViewModel> getIndividualViewModelStore(): ViewModelStore {
val viewModelKey = VIEWMODEL::class
var viewModelStore = individualModelStores[viewModelKey]
return if (viewModelStore != null) {
viewModelStore
} else {
viewModelStore = ViewModelStore()
individualModelStores[viewModelKey] = viewModelStore
return viewModelStore
}
}
inline fun <reified VIEWMODEL : ViewModel> clearIndividualViewModelStore() {
val viewModelKey = VIEWMODEL::class
individualModelStores[viewModelKey]?.clear()
individualModelStores.remove(viewModelKey)
}
}
Использование getSharedViewModel()
для получения экземпляра ViewModel, который связанк жизненному циклу Деятельности:
val yourViewModel : YourViewModel = (requireActivity() as MainActivity).getSharedViewModel(/*There could be some arguments in case of a more complex ViewModelProvider.Factory implementation*/)
Позже, когда пришло время избавиться от общей ViewModel, используйте clearIndividualViewModelStore<>()
:
(requireActivity() as MainActivity).clearIndividualViewModelStore<YourViewModel>()
В некоторых случаях вы захотите очистить ViewModelкак можно скорее, если он больше не нужен (например, если он содержит некоторые конфиденциальные данные пользователя, такие как имя пользователя или пароль).Вот способ записи состояния individualModelStores
при каждом переключении фрагмента, чтобы помочь вам отслеживать общие модели представления:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (BuildConfig.DEBUG) {
navController.addOnDestinationChangedListener { _, _, _ ->
if (individualModelStores.isNotEmpty()) {
val tag = this@MainActivity.javaClass.simpleName
Log.w(
tag,
"Don't forget to clear the shared ViewModelStores if they are not needed anymore."
)
Log.w(
tag,
"Currently there are ${individualModelStores.keys.size} ViewModelStores bound to ${this@MainActivity.javaClass.simpleName}:"
)
for ((index, viewModelClass) in individualModelStores.keys.withIndex()) {
Log.w(
tag,
"${index + 1}) $viewModelClass\n"
)
}
}
}
}
}