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
This commit is contained in:
Fabián Kozynski
2023-03-24 16:40:51 -04:00
parent 25be63a7bc
commit 6a22e3710f

View File

@@ -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 {