diff options
| author | 2023-03-24 16:40:51 -0400 | |
|---|---|---|
| committer | 2023-03-24 16:49:17 -0400 | |
| commit | 6a22e3710fe0751048f753f42a90074ede6b08ec (patch) | |
| tree | 787f08fa9f5f36f6c6c4aa3438389b556e3c9f6f | |
| parent | 25be63a7bc27c53be1de2c67bf4bc9ea228e73f5 (diff) | |
Remove pending runnables in QSTileView#changeState
When the view is not attached to a window, the runnables accumulate in
the view mRunQueue. If the view is never attached (for example, view in
the third page of QS), many of these can accumulate.
To fix, create a special runnable such that all instances are equal to
each other (so we can remove them). We cannot use the handler methods to
tag the runnable with a token because the problem arises when the view
is not attached (and therefore, there's no handler).
Test: manual, tiles get updated
Test: manual, using heapdump, check that runnables don't accumulate
Fixes: 269252339
Change-Id: I5371a19e1daf7b68eb3b152c5aa964774a372ebd
| -rw-r--r-- | packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt | 29 |
1 files changed, 26 insertions, 3 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt index de1137e48074..3090b793552f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt @@ -310,9 +310,15 @@ open class QSTileViewImpl @JvmOverloads constructor( } override fun onStateChanged(state: QSTile.State) { - post { - handleStateChanged(state) - } + // We cannot use the handler here because sometimes, the views are not attached (if they + // are in a page that the ViewPager hasn't attached). Instead, we use a runnable where + // all its instances are `equal` to each other, so they can be used to remove them from the + // queue. + // This means that at any given time there's at most one enqueued runnable to change state. + // However, as we only ever care about the last state posted, this is fine. + val runnable = StateChangeRunnable(state.copy()) + removeCallbacks(runnable) + post(runnable) } override fun getDetailY(): Int { @@ -650,6 +656,23 @@ open class QSTileViewImpl @JvmOverloads constructor( secondaryLabel.currentTextColor, chevronView.imageTintList?.defaultColor ?: 0 ) + + inner class StateChangeRunnable(private val state: QSTile.State) : Runnable { + override fun run() { + handleStateChanged(state) + } + + // We want all instances of this runnable to be equal to each other, so they can be used to + // remove previous instances from the Handler/RunQueue of this view + override fun equals(other: Any?): Boolean { + return other is StateChangeRunnable + } + + // This makes sure that all instances have the same hashcode (because they are `equal`) + override fun hashCode(): Int { + return StateChangeRunnable::class.hashCode() + } + } } fun constrainSquishiness(squish: Float): Float { |