Prevent destroyed activities from being reused

The adapter will cache a LayoutInflater which refers the current activity, and the ViewModel object will keep alive until activity finished. After activity recreates (e.g. split-screen), it will use the cached LayoutInflater which refers a destroyed activity and crashes. This also is a memory-leak, according to Google's official document, ViewModel shouldn't refer activity. See https://developer.android.com/topic/libraries/architecture/viewmodel

Fix topjohnwu#5413
This commit is contained in:
canyie 2022-03-07 01:04:21 +08:00 committed by John Wu
parent 0c681cdab4
commit 24505cd111
6 changed files with 6 additions and 6 deletions

View File

@ -5,6 +5,8 @@ import android.view.View
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.BaseFragment import com.topjohnwu.magisk.arch.BaseFragment
import com.topjohnwu.magisk.databinding.FragmentModuleMd2Binding import com.topjohnwu.magisk.databinding.FragmentModuleMd2Binding
import com.topjohnwu.magisk.databinding.RvItem
import com.topjohnwu.magisk.databinding.adapterOf
import com.topjohnwu.magisk.di.viewModel import com.topjohnwu.magisk.di.viewModel
import rikka.recyclerview.addEdgeSpacing import rikka.recyclerview.addEdgeSpacing
import rikka.recyclerview.addInvalidateItemDecorationsObserver import rikka.recyclerview.addInvalidateItemDecorationsObserver
@ -26,6 +28,7 @@ class ModuleFragment : BaseFragment<FragmentModuleMd2Binding>() {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
binding.moduleList.apply { binding.moduleList.apply {
adapter = adapterOf<RvItem>()
addEdgeSpacing(top = R.dimen.l_50, bottom = R.dimen.l1) addEdgeSpacing(top = R.dimen.l_50, bottom = R.dimen.l1)
addItemSpacing(R.dimen.l1, R.dimen.l_50, R.dimen.l1) addItemSpacing(R.dimen.l1, R.dimen.l_50, R.dimen.l1)
fixEdgeEffect() fixEdgeEffect()

View File

@ -8,7 +8,6 @@ import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.model.module.LocalModule import com.topjohnwu.magisk.core.model.module.LocalModule
import com.topjohnwu.magisk.core.model.module.OnlineModule import com.topjohnwu.magisk.core.model.module.OnlineModule
import com.topjohnwu.magisk.databinding.RvItem import com.topjohnwu.magisk.databinding.RvItem
import com.topjohnwu.magisk.databinding.adapterOf
import com.topjohnwu.magisk.databinding.diffListOf import com.topjohnwu.magisk.databinding.diffListOf
import com.topjohnwu.magisk.databinding.itemBindingOf import com.topjohnwu.magisk.databinding.itemBindingOf
import com.topjohnwu.magisk.events.SelectModuleEvent import com.topjohnwu.magisk.events.SelectModuleEvent
@ -26,7 +25,6 @@ class ModuleViewModel : BaseViewModel() {
private val itemsInstalled = diffListOf<LocalModuleRvItem>() private val itemsInstalled = diffListOf<LocalModuleRvItem>()
val adapter = adapterOf<RvItem>()
val items = MergeObservableList<RvItem>() val items = MergeObservableList<RvItem>()
val itemBinding = itemBindingOf<RvItem> { val itemBinding = itemBindingOf<RvItem> {
it.bindExtra(BR.viewModel, this) it.bindExtra(BR.viewModel, this)

View File

@ -4,7 +4,9 @@ import android.os.Bundle
import android.view.View import android.view.View
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.BaseFragment import com.topjohnwu.magisk.arch.BaseFragment
import com.topjohnwu.magisk.databinding.AnyDiffRvItem
import com.topjohnwu.magisk.databinding.FragmentSuperuserMd2Binding import com.topjohnwu.magisk.databinding.FragmentSuperuserMd2Binding
import com.topjohnwu.magisk.databinding.adapterOf
import com.topjohnwu.magisk.di.viewModel import com.topjohnwu.magisk.di.viewModel
import rikka.recyclerview.addEdgeSpacing import rikka.recyclerview.addEdgeSpacing
import rikka.recyclerview.addItemSpacing import rikka.recyclerview.addItemSpacing
@ -24,6 +26,7 @@ class SuperuserFragment : BaseFragment<FragmentSuperuserMd2Binding>() {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
binding.superuserList.apply { binding.superuserList.apply {
adapter = adapterOf<AnyDiffRvItem>()
addEdgeSpacing(top = R.dimen.l_50, bottom = R.dimen.l1) addEdgeSpacing(top = R.dimen.l_50, bottom = R.dimen.l1)
addItemSpacing(R.dimen.l1, R.dimen.l_50, R.dimen.l1) addItemSpacing(R.dimen.l1, R.dimen.l_50, R.dimen.l1)
fixEdgeEffect() fixEdgeEffect()

View File

@ -10,7 +10,6 @@ import com.topjohnwu.magisk.core.model.su.SuPolicy
import com.topjohnwu.magisk.core.utils.BiometricHelper import com.topjohnwu.magisk.core.utils.BiometricHelper
import com.topjohnwu.magisk.core.utils.currentLocale import com.topjohnwu.magisk.core.utils.currentLocale
import com.topjohnwu.magisk.databinding.AnyDiffRvItem import com.topjohnwu.magisk.databinding.AnyDiffRvItem
import com.topjohnwu.magisk.databinding.adapterOf
import com.topjohnwu.magisk.databinding.diffListOf import com.topjohnwu.magisk.databinding.diffListOf
import com.topjohnwu.magisk.databinding.itemBindingOf import com.topjohnwu.magisk.databinding.itemBindingOf
import com.topjohnwu.magisk.events.SnackbarEvent import com.topjohnwu.magisk.events.SnackbarEvent
@ -33,7 +32,6 @@ class SuperuserViewModel(
private val itemsPolicies = diffListOf<PolicyRvItem>() private val itemsPolicies = diffListOf<PolicyRvItem>()
private val itemsHelpers = ObservableArrayList<TextItem>() private val itemsHelpers = ObservableArrayList<TextItem>()
val adapter = adapterOf<AnyDiffRvItem>()
val items = MergeObservableList<AnyDiffRvItem>() val items = MergeObservableList<AnyDiffRvItem>()
.insertList(itemsHelpers) .insertList(itemsHelpers)
.insertList(itemsPolicies) .insertList(itemsPolicies)

View File

@ -19,7 +19,6 @@
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/module_list" android:id="@+id/module_list"
adapter="@{viewModel.adapter}"
gone="@{viewModel.loading}" gone="@{viewModel.loading}"
itemBinding="@{viewModel.itemBinding}" itemBinding="@{viewModel.itemBinding}"
items="@{viewModel.items}" items="@{viewModel.items}"

View File

@ -19,7 +19,6 @@
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/superuser_list" android:id="@+id/superuser_list"
adapter="@{viewModel.adapter}"
goneUnless="@{viewModel.loaded || !viewModel.items.empty}" goneUnless="@{viewModel.loaded || !viewModel.items.empty}"
itemBinding="@{viewModel.itemBinding}" itemBinding="@{viewModel.itemBinding}"
items="@{viewModel.items}" items="@{viewModel.items}"