Skip to content

Commit c3dade1

Browse files
committed
fix: 修复调度问题
1 parent 1cb1622 commit c3dade1

File tree

1 file changed

+28
-7
lines changed

1 file changed

+28
-7
lines changed

cxrv/src/main/kotlin/com/xiaocydx/cxrv/internal/Traversal.kt

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.xiaocydx.cxrv.internal
1818

1919
import android.content.Context
20+
import android.graphics.Canvas
2021
import android.view.Choreographer
2122
import android.view.Choreographer.FrameCallback
2223
import android.view.KeyEvent
@@ -88,10 +89,13 @@ private class BroadcastProxy(private val view: View) {
8889
return
8990
}
9091
callbacks += callback
91-
view.requestLayout()
9292
broadcastFrame?.scheduleTraversal()
9393
}
9494

95+
fun requestLayoutIfNecessary() {
96+
if (callbacks.size > 0) view.requestLayout()
97+
}
98+
9599
fun removeTraversalCallback(callback: FrameCallback) {
96100
callbacks -= callback
97101
}
@@ -116,13 +120,10 @@ private class BroadcastProxy(private val view: View) {
116120
}
117121

118122
private class BroadcastFrame private constructor(context: Context) : View(context) {
119-
private var canUnregisterOnDetached = true
123+
private val scheduleTraversalRunner = Runnable { scheduleTraversal() }
120124
private var proxyList = InlineList<BroadcastProxy>()
121-
122-
init {
123-
setWillNotDraw(true)
124-
visibility = INVISIBLE
125-
}
125+
private var canUnregisterOnDetached = true
126+
private var isScheduled = false
126127

127128
fun register(proxy: BroadcastProxy) {
128129
proxyList += proxy
@@ -133,6 +134,9 @@ private class BroadcastFrame private constructor(context: Context) : View(contex
133134
}
134135

135136
fun scheduleTraversal() {
137+
removeCallbacks(scheduleTraversalRunner)
138+
proxyList.reverseAccessEach { it.requestLayoutIfNecessary() }
139+
136140
ensureFirstMeasure()
137141
requestLayout()
138142
if (parent !is FrameLayout) {
@@ -141,6 +145,13 @@ private class BroadcastFrame private constructor(context: Context) : View(contex
141145
// requestApplyInsets()是替补方案,尽可能让BroadcastFrame在其它child之前执行。
142146
requestApplyInsets()
143147
}
148+
149+
// 调用scheduleTraversal()时,当前可能处于measure、layout阶段,
150+
// 此时调用requestLayout()会被parent的flag拦截,不会有下一帧。
151+
// 因此调用invalidate(),在onDraw()判断isScheduled是否被重置,
152+
// 若isScheduled未被重置,则表示被拦截,需要重新调度。
153+
invalidate()
154+
isScheduled = true
144155
}
145156

146157
override fun dispatchApplyWindowInsets(insets: WindowInsets): WindowInsets {
@@ -153,7 +164,16 @@ private class BroadcastFrame private constructor(context: Context) : View(contex
153164
setMeasuredDimension(0, 0)
154165
}
155166

167+
override fun onDraw(canvas: Canvas) {
168+
if (isScheduled) {
169+
isScheduled = false
170+
// 前置流程可能会添加同步屏障,因此不使用post()
171+
postOnAnimation(scheduleTraversalRunner)
172+
}
173+
}
174+
156175
private fun consumeTraversalCallbacks() {
176+
isScheduled = false
157177
proxyList.reverseAccessEach { it.consumeTraversalCallbacks() }
158178
}
159179

@@ -171,6 +191,7 @@ private class BroadcastFrame private constructor(context: Context) : View(contex
171191
override fun onDetachedFromWindow() {
172192
super.onDetachedFromWindow()
173193
if (!canUnregisterOnDetached) return
194+
removeCallbacks(scheduleTraversalRunner)
174195
proxyList.reverseAccessEach { it.unregisterFromBroadcastFrame() }
175196
proxyList = proxyList.clear()
176197
}

0 commit comments

Comments
 (0)