Android: Make SettingViewHolder a LifecycleOwner

This commit is contained in:
JosJuice
2025-05-13 14:31:57 +02:00
parent 4214cb6eb8
commit 5d7cba8cd9
5 changed files with 94 additions and 3 deletions

View File

@ -16,6 +16,7 @@ import androidx.annotation.ColorInt
import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.Lifecycle
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.color.MaterialColors
import com.google.android.material.datepicker.CalendarConstraints
@ -543,6 +544,25 @@ class SettingsAdapter(
}
}
override fun onViewRecycled(holder: SettingViewHolder) {
super.onViewRecycled(holder)
holder.onViewRecycled()
}
override fun onViewAttachedToWindow(holder: SettingViewHolder) {
super.onViewAttachedToWindow(holder)
holder.onViewAttachedToWindow()
}
override fun onViewDetachedFromWindow(holder: SettingViewHolder) {
super.onViewDetachedFromWindow(holder)
holder.onViewDetachedFromWindow()
}
fun getFragmentLifecycle(): Lifecycle {
return fragmentView.getFragmentLifecycle()
}
private fun getValueForSingleChoiceSelection(item: SingleChoiceSetting, which: Int): Int {
val valuesId = item.valuesId

View File

@ -18,6 +18,7 @@ import androidx.core.view.updatePadding
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.Lifecycle
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar
@ -25,7 +26,6 @@ import org.dolphinemu.dolphinemu.R
import org.dolphinemu.dolphinemu.databinding.FragmentSettingsBinding
import org.dolphinemu.dolphinemu.features.settings.model.Settings
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
import org.dolphinemu.dolphinemu.ui.main.MainActivity
import org.dolphinemu.dolphinemu.ui.main.MainPresenter
import org.dolphinemu.dolphinemu.utils.GpuDriverInstallResult
import org.dolphinemu.dolphinemu.utils.SerializableHelper.serializable
@ -200,6 +200,10 @@ class SettingsFragment : Fragment(), SettingsFragmentView {
.show()
}
override fun getFragmentLifecycle(): Lifecycle {
return lifecycle
}
private fun askForDriverFile() {
val intent = Intent(Intent.ACTION_GET_CONTENT).apply {
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)

View File

@ -4,6 +4,7 @@ package org.dolphinemu.dolphinemu.features.settings.ui
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.Lifecycle
import org.dolphinemu.dolphinemu.features.settings.model.Settings
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
import org.dolphinemu.dolphinemu.utils.GpuDriverInstallResult
@ -119,4 +120,9 @@ interface SettingsFragmentView {
* Shows a dialog asking the user to install or uninstall a GPU driver
*/
fun showGpuDriverDialog()
/**
* Returns the Lifecycle for the Fragment.
*/
fun getFragmentLifecycle(): Lifecycle
}

View File

@ -9,15 +9,17 @@ import android.view.View
import android.view.View.OnLongClickListener
import android.widget.TextView
import android.widget.Toast
import androidx.recyclerview.widget.RecyclerView
import androidx.lifecycle.LifecycleOwner
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.dolphinemu.dolphinemu.DolphinApplication
import org.dolphinemu.dolphinemu.R
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter
import org.dolphinemu.dolphinemu.utils.LifecycleViewHolder
abstract class SettingViewHolder(itemView: View, protected val adapter: SettingsAdapter) :
RecyclerView.ViewHolder(itemView), View.OnClickListener, OnLongClickListener {
LifecycleViewHolder(itemView, adapter.getFragmentLifecycle()),
LifecycleOwner, View.OnClickListener, OnLongClickListener {
init {
itemView.setOnClickListener(this)

View File

@ -0,0 +1,59 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.utils
import android.view.View
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LifecycleRegistry
import androidx.recyclerview.widget.RecyclerView
/**
* A ViewHolder with an attached Lifecycle.
*
* @param itemView The view held by the ViewHolder.
* @param parentLifecycle If the passed-in Lifecycle changes state to DESTROYED, this ViewHolder
* will also change state to DESTROYED. This should normally be set to the
* Lifecycle of the containing Fragment or Activity to prevent instances
* of this class from leaking.
*/
abstract class LifecycleViewHolder(itemView: View, parentLifecycle: Lifecycle) :
RecyclerView.ViewHolder(itemView), LifecycleOwner {
private val lifecycleRegistry = LifecycleRegistry(this)
override val lifecycle: Lifecycle
get() = lifecycleRegistry
init {
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE)
parentLifecycle.addObserver(object : DefaultLifecycleObserver {
override fun onDestroy(owner: LifecycleOwner) {
// Make sure this ViewHolder doesn't leak if its lifecycle has observers
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY)
}
})
}
/**
* To be called from a function overriding [RecyclerView.Adapter.onViewRecycled].
*/
fun onViewRecycled() {
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP)
}
/**
* To be called from a function overriding [RecyclerView.Adapter.onViewAttachedToWindow].
*/
fun onViewAttachedToWindow() {
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME)
}
/**
* To be called from a function overriding [RecyclerView.Adapter.onViewDetachedFromWindow].
*/
fun onViewDetachedFromWindow() {
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP)
}
}