From 4a955a1959e03c72f401b0d6547fc19dfd41d329 Mon Sep 17 00:00:00 2001 From: Rocka Date: Sun, 9 Nov 2025 02:10:26 +0800 Subject: [PATCH] Clear callbacks on CandidateViewHolder once recycled hopefully fixes some weird crash --- .../window/BaseExpandedCandidateWindow.kt | 9 +++++++-- .../window/FlexboxExpandedCandidateWindow.kt | 7 ++++++- .../window/GridExpandedCandidateWindow.kt | 7 ++++++- .../candidates/floating/PagedCandidatesUi.kt | 9 ++++++++- .../HorizontalCandidateComponent.kt | 20 +++++++++++++------ 5 files changed, 41 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/org/fcitx/fcitx5/android/input/candidates/expanded/window/BaseExpandedCandidateWindow.kt b/app/src/main/java/org/fcitx/fcitx5/android/input/candidates/expanded/window/BaseExpandedCandidateWindow.kt index 8b87ab58..eeb5f77a 100644 --- a/app/src/main/java/org/fcitx/fcitx5/android/input/candidates/expanded/window/BaseExpandedCandidateWindow.kt +++ b/app/src/main/java/org/fcitx/fcitx5/android/input/candidates/expanded/window/BaseExpandedCandidateWindow.kt @@ -1,6 +1,6 @@ /* * SPDX-License-Identifier: LGPL-2.1-or-later - * SPDX-FileCopyrightText: Copyright 2021-2024 Fcitx5 for Android Contributors + * SPDX-FileCopyrightText: Copyright 2021-2025 Fcitx5 for Android Contributors */ package org.fcitx.fcitx5.android.input.candidates.expanded.window @@ -143,11 +143,16 @@ abstract class BaseExpandedCandidateWindow> : fcitx.launchOnReady { it.select(holder.idx) } } holder.itemView.setOnLongClickListener { - horizontalCandidate.showCandidateActionMenu(holder.idx, holder.text, holder.ui) + horizontalCandidate.showCandidateActionMenu(holder) true } } + fun recycleCandidateViewHolder(holder: CandidateViewHolder) { + holder.itemView.setOnClickListener(null) + holder.itemView.setOnLongClickListener(null) + } + override fun onDetached() { bar.expandButtonStateMachine.push( ExpandedCandidatesDetached, diff --git a/app/src/main/java/org/fcitx/fcitx5/android/input/candidates/expanded/window/FlexboxExpandedCandidateWindow.kt b/app/src/main/java/org/fcitx/fcitx5/android/input/candidates/expanded/window/FlexboxExpandedCandidateWindow.kt index b63d4b0c..180c5232 100644 --- a/app/src/main/java/org/fcitx/fcitx5/android/input/candidates/expanded/window/FlexboxExpandedCandidateWindow.kt +++ b/app/src/main/java/org/fcitx/fcitx5/android/input/candidates/expanded/window/FlexboxExpandedCandidateWindow.kt @@ -1,6 +1,6 @@ /* * SPDX-License-Identifier: LGPL-2.1-or-later - * SPDX-FileCopyrightText: Copyright 2021-2024 Fcitx5 for Android Contributors + * SPDX-FileCopyrightText: Copyright 2021-2025 Fcitx5 for Android Contributors */ package org.fcitx.fcitx5.android.input.candidates.expanded.window @@ -40,6 +40,11 @@ class FlexboxExpandedCandidateWindow : super.onBindViewHolder(holder, position) bindCandidateUiViewHolder(holder) } + + override fun onViewRecycled(holder: CandidateViewHolder) { + recycleCandidateViewHolder(holder) + super.onViewRecycled(holder) + } } } diff --git a/app/src/main/java/org/fcitx/fcitx5/android/input/candidates/expanded/window/GridExpandedCandidateWindow.kt b/app/src/main/java/org/fcitx/fcitx5/android/input/candidates/expanded/window/GridExpandedCandidateWindow.kt index dc365a5b..23316d73 100644 --- a/app/src/main/java/org/fcitx/fcitx5/android/input/candidates/expanded/window/GridExpandedCandidateWindow.kt +++ b/app/src/main/java/org/fcitx/fcitx5/android/input/candidates/expanded/window/GridExpandedCandidateWindow.kt @@ -1,6 +1,6 @@ /* * SPDX-License-Identifier: LGPL-2.1-or-later - * SPDX-FileCopyrightText: Copyright 2021-2024 Fcitx5 for Android Contributors + * SPDX-FileCopyrightText: Copyright 2021-2025 Fcitx5 for Android Contributors */ package org.fcitx.fcitx5.android.input.candidates.expanded.window @@ -35,6 +35,11 @@ class GridExpandedCandidateWindow : super.onBindViewHolder(holder, position) bindCandidateUiViewHolder(holder) } + + override fun onViewRecycled(holder: CandidateViewHolder) { + recycleCandidateViewHolder(holder) + super.onViewRecycled(holder) + } } } diff --git a/app/src/main/java/org/fcitx/fcitx5/android/input/candidates/floating/PagedCandidatesUi.kt b/app/src/main/java/org/fcitx/fcitx5/android/input/candidates/floating/PagedCandidatesUi.kt index dd5bb7bc..69765841 100644 --- a/app/src/main/java/org/fcitx/fcitx5/android/input/candidates/floating/PagedCandidatesUi.kt +++ b/app/src/main/java/org/fcitx/fcitx5/android/input/candidates/floating/PagedCandidatesUi.kt @@ -1,6 +1,6 @@ /* * SPDX-License-Identifier: LGPL-2.1-or-later - * SPDX-FileCopyrightText: Copyright 2024 Fcitx5 for Android Contributors + * SPDX-FileCopyrightText: Copyright 2025 Fcitx5 for Android Contributors */ package org.fcitx.fcitx5.android.input.candidates.floating @@ -94,6 +94,13 @@ class PagedCandidatesUi( } } } + + override fun onViewRecycled(holder: UiHolder) { + if (holder is UiHolder.Candidate) { + holder.ui.root.setOnClickListener(null) + } + super.onViewRecycled(holder) + } } private val candidatesLayoutManager = FlexboxLayoutManager(ctx).apply { diff --git a/app/src/main/java/org/fcitx/fcitx5/android/input/candidates/horizontal/HorizontalCandidateComponent.kt b/app/src/main/java/org/fcitx/fcitx5/android/input/candidates/horizontal/HorizontalCandidateComponent.kt index 29719e4b..b7ff4cd3 100644 --- a/app/src/main/java/org/fcitx/fcitx5/android/input/candidates/horizontal/HorizontalCandidateComponent.kt +++ b/app/src/main/java/org/fcitx/fcitx5/android/input/candidates/horizontal/HorizontalCandidateComponent.kt @@ -1,6 +1,6 @@ /* * SPDX-License-Identifier: LGPL-2.1-or-later - * SPDX-FileCopyrightText: Copyright 2021-2024 Fcitx5 for Android Contributors + * SPDX-FileCopyrightText: Copyright 2021-2025 Fcitx5 for Android Contributors */ package org.fcitx.fcitx5.android.input.candidates.horizontal @@ -29,7 +29,6 @@ import org.fcitx.fcitx5.android.input.bar.ExpandButtonStateMachine.BooleanKey.Ex import org.fcitx.fcitx5.android.input.bar.ExpandButtonStateMachine.TransitionEvent.ExpandedCandidatesUpdated import org.fcitx.fcitx5.android.input.bar.KawaiiBarComponent import org.fcitx.fcitx5.android.input.broadcast.InputBroadcastReceiver -import org.fcitx.fcitx5.android.input.candidates.CandidateItemUi import org.fcitx.fcitx5.android.input.candidates.CandidateViewHolder import org.fcitx.fcitx5.android.input.candidates.expanded.decoration.FlexboxVerticalDecoration import org.fcitx.fcitx5.android.input.candidates.horizontal.HorizontalCandidateMode.AlwaysFillWidth @@ -106,10 +105,16 @@ class HorizontalCandidateComponent : fcitx.launchOnReady { it.select(holder.idx) } } holder.itemView.setOnLongClickListener { - showCandidateActionMenu(holder.idx, candidates[position], holder.ui) + showCandidateActionMenu(holder) true } } + + override fun onViewRecycled(holder: CandidateViewHolder) { + holder.itemView.setOnClickListener(null) + holder.itemView.setOnLongClickListener(null) + super.onViewRecycled(holder) + } } } @@ -206,14 +211,17 @@ class HorizontalCandidateComponent : private var candidateActionMenu: PopupMenu? = null - fun showCandidateActionMenu(idx: Int, text: String, ui: CandidateItemUi) { + fun showCandidateActionMenu(holder: CandidateViewHolder) { + val idx = holder.idx + val text = holder.text + val view = holder.ui.root candidateActionMenu?.dismiss() candidateActionMenu = null service.lifecycleScope.launch { val actions = fcitx.runOnReady { getCandidateActions(idx) } if (actions.isEmpty()) return@launch - InputFeedbacks.hapticFeedback(ui.root, longPress = true) - candidateActionMenu = PopupMenu(context, ui.root).apply { + InputFeedbacks.hapticFeedback(view, longPress = true) + candidateActionMenu = PopupMenu(context, view).apply { menu.add(buildSpannedString { bold { color(context.styledColor(android.R.attr.colorAccent)) {