From e496bdf82d15b3e7f5b19e08a404224138615514 Mon Sep 17 00:00:00 2001 From: Mike22 Date: Sat, 27 Dec 2025 12:58:17 +0100 Subject: [PATCH] Android UI - Fix adapter observer lifecycle Move carousel observer registration to setAdapter() so it is bound to the adapter lifecycle. This prevents repeated observer registration during carousel setup and eliminates duplicate refresh and focus callbacks after changes to the view type. --- .../yuzu_emu/views/CarouselRecyclerView.kt | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/views/CarouselRecyclerView.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/views/CarouselRecyclerView.kt index 33ca9ff328..aea4a3b943 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/views/CarouselRecyclerView.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/views/CarouselRecyclerView.kt @@ -55,6 +55,16 @@ class CarouselRecyclerView @JvmOverloads constructor( private val preferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) + private val carouselAdapterObserver = object : RecyclerView.AdapterDataObserver() { + override fun onChanged() { + if (!pendingScrollAfterReload) return + doOnNextLayout { + refreshView() + pendingScrollAfterReload = false + } + } + } + var flingMultiplier: Float = 1f var pendingScrollAfterReload: Boolean = false @@ -70,6 +80,18 @@ class CarouselRecyclerView @JvmOverloads constructor( setChildrenDrawingOrderEnabled(true) } + override fun setAdapter(adapter: Adapter<*>?) { + val oldAdapter = this.adapter as? GameAdapter + + if (oldAdapter !== adapter) { + oldAdapter?.unregisterAdapterDataObserver(carouselAdapterObserver) + } + + super.setAdapter(adapter) + + (adapter as? GameAdapter)?.registerAdapterDataObserver(carouselAdapterObserver) + } + private fun calculateCenter(width: Int, paddingStart: Int, paddingEnd: Int): Int { return paddingStart + (width - paddingStart - paddingEnd) / 2 } @@ -252,17 +274,6 @@ class CarouselRecyclerView @JvmOverloads constructor( internalFlingMultiplier ).coerceIn(1f, 5f) - gameAdapter .registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() { - override fun onChanged() { - if (pendingScrollAfterReload) { - doOnNextLayout { - refreshView() - pendingScrollAfterReload = false - } - } - } - }) - // Detach SnapHelper during setup pagerSnapHelper?.attachToRecyclerView(null)