Skip to content

Commit

Permalink
fix: 限制节点数量避免内存溢出
Browse files Browse the repository at this point in the history
  • Loading branch information
lisonge committed Oct 8, 2023
1 parent c029a38 commit 8074175
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 45 deletions.
101 changes: 64 additions & 37 deletions app/src/main/java/li/songe/gkd/service/AbExt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -96,47 +96,74 @@ private fun AccessibilityNodeInfo.getTempRect(): Rect {
return tempRect
}

val abTransform = Transform<AccessibilityNodeInfo>(
getAttr = { node, name ->
when (name) {
"id" -> node.viewIdResourceName
"name" -> node.className
"text" -> node.text
"text.length" -> node.text?.length
"desc" -> node.contentDescription
"desc.length" -> node.contentDescription?.length

"clickable" -> node.isClickable
"checkable" -> node.isCheckable
"checked" -> node.isChecked
"focusable" -> node.isFocusable
"visibleToUser" -> node.isVisibleToUser

"left" -> node.getTempRect().left
"top" -> node.getTempRect().top
"right" -> node.getTempRect().right
"bottom" -> node.getTempRect().bottom

"width" -> node.getTempRect().width()
"height" -> node.getTempRect().height()

"index" -> node.getIndex()
"depth" -> node.getDepth()
"childCount" -> node.childCount
else -> null

// https://github.com/gkd-kit/gkd/issues/115
private const val MAX_CHILD_SIZE = 256
private const val MAX_DESCENDANTS_SIZE = 4096

private val getChildren: (AccessibilityNodeInfo) -> Sequence<AccessibilityNodeInfo> = { node ->
sequence {
repeat(node.childCount.coerceAtMost(MAX_CHILD_SIZE)) { i ->
val child = node.getChild(i) ?: return@sequence
yield(child)
}
},
}
}

private val getAttr: (AccessibilityNodeInfo, String) -> Any? = { node, name ->
when (name) {
"id" -> node.viewIdResourceName
"name" -> node.className
"text" -> node.text
"text.length" -> node.text?.length
"desc" -> node.contentDescription
"desc.length" -> node.contentDescription?.length

"clickable" -> node.isClickable
"checkable" -> node.isCheckable
"checked" -> node.isChecked
"focusable" -> node.isFocusable
"visibleToUser" -> node.isVisibleToUser

"left" -> node.getTempRect().left
"top" -> node.getTempRect().top
"right" -> node.getTempRect().right
"bottom" -> node.getTempRect().bottom

"width" -> node.getTempRect().width()
"height" -> node.getTempRect().height()

"index" -> node.getIndex()
"depth" -> node.getDepth()
"childCount" -> node.childCount
else -> null
}
}

val abTransform = Transform(getAttr = getAttr,
getName = { node -> node.className },
getChildren = { node ->
sequence {
repeat(node.childCount) { i ->
yield(node.getChild(i))
}
}
},
getChildren = getChildren,
getChild = { node, index -> node.getChild(index) },
getParent = { node -> node.parent },
)
getDescendants = { node ->
sequence {
val stack = mutableListOf(node)
val tempNodes = mutableListOf<AccessibilityNodeInfo>()
do {
val top = stack.removeLast()
yield(top)
for (childNode in getChildren(top)) {
tempNodes.add(childNode)
}
if (tempNodes.isNotEmpty()) {
for (i in tempNodes.size - 1 downTo 0) {
stack.add(tempNodes[i])
}
tempNodes.clear()
}
} while (stack.isNotEmpty())
}.take(MAX_DESCENDANTS_SIZE)
})

private var lastToastTime = -1L
fun toastClickTip() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import kotlin.js.JsExport
class CommonTransform<T : Any>(
getAttr: (T, String) -> Any?,
getName: (T) -> String?,
getChildren: (T) -> Array<T?>,
getChildren: (T) -> Array<T>,
getParent: (T) -> T?,
) {
internal val transform = Transform(
Expand All @@ -18,26 +18,27 @@ class CommonTransform<T : Any>(
getParent = getParent,
)

@Suppress("UNCHECKED_CAST")
@Suppress("UNCHECKED_CAST", "UNUSED")
val querySelectorAll: (T, CommonSelector) -> Array<T> = { node, selector ->
val result =
transform.querySelectorAll(node, selector.selector).toList().toTypedArray<Any?>()
result as Array<T>
}

@Suppress("UNUSED")
val querySelector: (T, CommonSelector) -> T? = { node, selector ->
transform.querySelectorAll(node, selector.selector).firstOrNull()
}


@Suppress("UNCHECKED_CAST")
@Suppress("UNCHECKED_CAST", "UNUSED")
val querySelectorTrackAll: (T, CommonSelector) -> Array<Array<T>> = { node, selector ->
val result = transform.querySelectorTrackAll(node, selector.selector)
.map { it.toTypedArray<Any?>() as Array<T> }.toList().toTypedArray<Any?>()
result as Array<Array<T>>
}

@Suppress("UNCHECKED_CAST")
@Suppress("UNCHECKED_CAST", "UNUSED")
val querySelectorTrack: (T, CommonSelector) -> Array<T>? = { node, selector ->
transform.querySelectorTrackAll(node, selector.selector).firstOrNull()
?.toTypedArray<Any?>() as Array<T>?
Expand Down
9 changes: 5 additions & 4 deletions selector/src/commonMain/kotlin/li/songe/selector/Transform.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ package li.songe.selector
class Transform<T>(
val getAttr: (T, String) -> Any?,
val getName: (T) -> CharSequence?,
val getChildren: (T) -> Sequence<T?>,
val getChildren: (T) -> Sequence<T>,
val getChild: (T, Int) -> T? = { node, offset -> getChildren(node).elementAtOrNull(offset) },
val getParent: (T) -> T?,
val getAncestors: (T) -> Sequence<T> = { node ->
Expand Down Expand Up @@ -55,9 +55,7 @@ class Transform<T>(
val top = stack.removeLast()
yield(top)
for (childNode in getChildren(top)) {
if (childNode != null) {
tempNodes.add(childNode)
}
tempNodes.add(childNode)
}
if (tempNodes.isNotEmpty()) {
for (i in tempNodes.size - 1 downTo 0) {
Expand All @@ -70,6 +68,7 @@ class Transform<T>(
},

) {

val querySelectorAll: (T, Selector) -> Sequence<T> = { node, selector ->
sequence {
val trackNodes: MutableList<T> = mutableListOf()
Expand All @@ -95,6 +94,8 @@ class Transform<T>(
}
}
}

@Suppress("UNUSED")
val querySelectorTrack: (T, Selector) -> List<T>? = { node, selector ->
querySelectorTrackAll(
node, selector
Expand Down

0 comments on commit 8074175

Please sign in to comment.