Remove warnings
Summary: ^ Reviewed By: LukeDefeo Differential Revision: D39573417 fbshipit-source-id: 241ecdddaf43020923046b0b5c35656bc8ffad34
This commit is contained in:
committed by
Facebook GitHub Bot
parent
3a4286b2ba
commit
d8e47efb81
@@ -9,10 +9,8 @@ package com.facebook.flipper.plugins.uidebugger.commands
|
|||||||
|
|
||||||
import com.facebook.flipper.core.FlipperConnection
|
import com.facebook.flipper.core.FlipperConnection
|
||||||
|
|
||||||
sealed class CommandRegister {
|
object CommandRegister {
|
||||||
companion object {
|
|
||||||
fun <T> register(connection: FlipperConnection, cmd: T) where T : Command {
|
fun <T> register(connection: FlipperConnection, cmd: T) where T : Command {
|
||||||
connection.receive(cmd.identifier(), cmd.receiver())
|
connection.receive(cmd.identifier(), cmd.receiver())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -11,32 +11,30 @@ import android.util.Log
|
|||||||
import com.facebook.flipper.plugins.uidebugger.LogTag
|
import com.facebook.flipper.plugins.uidebugger.LogTag
|
||||||
|
|
||||||
// Maintains 2 way mapping between some enum value and a readable string representation
|
// Maintains 2 way mapping between some enum value and a readable string representation
|
||||||
open class EnumMapping<T>(val mapping: Map<String, T>) {
|
open class EnumMapping<T>(private val mapping: Map<String, T>) {
|
||||||
|
|
||||||
fun getStringRepresentation(enumValue: T): String {
|
fun getStringRepresentation(enumValue: T): String {
|
||||||
val entry = mapping.entries.find { (_, value) -> value == enumValue }
|
val entry = mapping.entries.find { (_, value) -> value == enumValue }
|
||||||
if (entry != null) {
|
return if (entry != null) {
|
||||||
return entry.key
|
entry.key
|
||||||
} else {
|
} else {
|
||||||
Log.v(
|
Log.v(
|
||||||
LogTag,
|
LogTag,
|
||||||
"Could not convert enum value ${enumValue.toString()} to string, known values ${mapping.entries}")
|
"Could not convert enum value ${enumValue.toString()} to string, known values ${mapping.entries}")
|
||||||
return NoMapping
|
NoMapping
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getEnumValue(key: String): T {
|
fun getEnumValue(key: String): T {
|
||||||
val value =
|
return mapping[key]
|
||||||
mapping[key]
|
|
||||||
?: throw UIDebuggerException(
|
?: throw UIDebuggerException(
|
||||||
"Could not convert string ${key} to enum value, possible values ${mapping.entries} ")
|
"Could not convert string $key to enum value, possible values ${mapping.entries} ")
|
||||||
return value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toInspectable(value: T, mutable: Boolean): InspectableValue.Enum {
|
fun toInspectable(value: T, mutable: Boolean): InspectableValue.Enum {
|
||||||
return InspectableValue.Enum(EnumData(mapping.keys, getStringRepresentation(value)), mutable)
|
return InspectableValue.Enum(EnumData(mapping.keys, getStringRepresentation(value)), mutable)
|
||||||
}
|
}
|
||||||
companion object {
|
companion object {
|
||||||
val NoMapping = "__UNKNOWN_ENUM_VALUE__"
|
const val NoMapping = "__UNKNOWN_ENUM_VALUE__"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ class LayoutTraversal(
|
|||||||
val root: ApplicationRef
|
val root: ApplicationRef
|
||||||
) {
|
) {
|
||||||
|
|
||||||
internal inline fun NodeDescriptor<*>.asAny(): NodeDescriptor<Any> = this as NodeDescriptor<Any>
|
@Suppress("unchecked_cast")
|
||||||
|
internal fun NodeDescriptor<*>.asAny(): NodeDescriptor<Any> = this as NodeDescriptor<Any>
|
||||||
|
|
||||||
/** Traverses the native android hierarchy */
|
/** Traverses the native android hierarchy */
|
||||||
fun traverse(): List<Node> {
|
fun traverse(): List<Node> {
|
||||||
@@ -69,7 +70,7 @@ class LayoutTraversal(
|
|||||||
childrenIds,
|
childrenIds,
|
||||||
activeChildId))
|
activeChildId))
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
Log.e(LogTag, "Error while processing node ${node.javaClass.name} ${node} ", exception)
|
Log.e(LogTag, "Error while processing node ${node.javaClass.name} $node", exception)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ package com.facebook.flipper.plugins.uidebugger.core
|
|||||||
|
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.LogTag
|
||||||
import com.facebook.flipper.plugins.uidebugger.model.NativeScanEvent
|
import com.facebook.flipper.plugins.uidebugger.model.NativeScanEvent
|
||||||
import com.facebook.flipper.plugins.uidebugger.model.Node
|
import com.facebook.flipper.plugins.uidebugger.model.Node
|
||||||
import com.facebook.flipper.plugins.uidebugger.model.PerfStatsEvent
|
import com.facebook.flipper.plugins.uidebugger.model.PerfStatsEvent
|
||||||
@@ -23,26 +24,24 @@ data class ScanResult(
|
|||||||
)
|
)
|
||||||
|
|
||||||
class NativeScanScheduler(val context: Context) : Scheduler.Task<ScanResult> {
|
class NativeScanScheduler(val context: Context) : Scheduler.Task<ScanResult> {
|
||||||
val traversal = LayoutTraversal(context.descriptorRegister, context.applicationRef)
|
private val traversal = LayoutTraversal(context.descriptorRegister, context.applicationRef)
|
||||||
var txId = 0L
|
private var txId = 0L
|
||||||
override fun execute(): ScanResult {
|
|
||||||
|
|
||||||
|
override fun execute(): ScanResult {
|
||||||
val start = System.currentTimeMillis()
|
val start = System.currentTimeMillis()
|
||||||
val nodes = traversal.traverse()
|
val nodes = traversal.traverse()
|
||||||
val scanEnd = System.currentTimeMillis()
|
val scanEnd = System.currentTimeMillis()
|
||||||
|
|
||||||
Log.d(
|
Log.d(
|
||||||
"LAYOUT_SCHEDULER",
|
LogTag,
|
||||||
"${Thread.currentThread().name}${Looper.myLooper()} produced: ${nodes.count()} nodes")
|
"${Thread.currentThread().name}${Looper.myLooper()} produced: ${nodes.count()} nodes")
|
||||||
|
|
||||||
return ScanResult(txId++, start, scanEnd, nodes)
|
return ScanResult(txId++, start, scanEnd, nodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun process(result: ScanResult) {
|
override fun process(input: ScanResult) {
|
||||||
|
|
||||||
val serialized =
|
val serialized =
|
||||||
Json.encodeToString(
|
Json.encodeToString(NativeScanEvent.serializer(), NativeScanEvent(input.txId, input.nodes))
|
||||||
NativeScanEvent.serializer(), NativeScanEvent(result.txId, result.nodes))
|
|
||||||
val serializationEnd = System.currentTimeMillis()
|
val serializationEnd = System.currentTimeMillis()
|
||||||
context.connectionRef.connection?.send(
|
context.connectionRef.connection?.send(
|
||||||
NativeScanEvent.name,
|
NativeScanEvent.name,
|
||||||
@@ -56,13 +55,13 @@ class NativeScanScheduler(val context: Context) : Scheduler.Task<ScanResult> {
|
|||||||
Json.encodeToString(
|
Json.encodeToString(
|
||||||
PerfStatsEvent.serializer(),
|
PerfStatsEvent.serializer(),
|
||||||
PerfStatsEvent(
|
PerfStatsEvent(
|
||||||
result.txId,
|
input.txId,
|
||||||
"FullScan",
|
"FullScan",
|
||||||
result.scanStart,
|
input.scanStart,
|
||||||
result.scanEnd,
|
input.scanEnd,
|
||||||
result.scanEnd,
|
input.scanEnd,
|
||||||
serializationEnd,
|
serializationEnd,
|
||||||
socketEnd,
|
socketEnd,
|
||||||
result.nodes.size)))
|
input.nodes.size)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,25 +120,28 @@ class RootViewResolver {
|
|||||||
if (null == paramsField) {
|
if (null == paramsField) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
var views: List<View>? = null
|
var maybeViews: List<View>? = null
|
||||||
var params: List<WindowManager.LayoutParams>? = null
|
var maybeParams: List<WindowManager.LayoutParams>? = null
|
||||||
try {
|
try {
|
||||||
viewsField?.let { field ->
|
viewsField?.let { field ->
|
||||||
views =
|
maybeViews =
|
||||||
if (Build.VERSION.SDK_INT < 19) {
|
if (Build.VERSION.SDK_INT < 19) {
|
||||||
val arr = field[windowManagerObj] as Array<View>
|
@Suppress("unchecked_cast") val arr = field[windowManagerObj] as Array<View>
|
||||||
arr.toList()
|
arr.toList()
|
||||||
} else {
|
} else {
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
field[windowManagerObj] as List<View>
|
field[windowManagerObj] as List<View>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsField?.let { field ->
|
paramsField?.let { field ->
|
||||||
params =
|
maybeParams =
|
||||||
if (Build.VERSION.SDK_INT < 19) {
|
if (Build.VERSION.SDK_INT < 19) {
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
val arr = field[windowManagerObj] as Array<WindowManager.LayoutParams>
|
val arr = field[windowManagerObj] as Array<WindowManager.LayoutParams>
|
||||||
arr.toList() as List<WindowManager.LayoutParams>
|
arr.toList()
|
||||||
} else {
|
} else {
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
field[windowManagerObj] as List<WindowManager.LayoutParams>
|
field[windowManagerObj] as List<WindowManager.LayoutParams>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -149,8 +152,8 @@ class RootViewResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val roots = mutableListOf<RootView>()
|
val roots = mutableListOf<RootView>()
|
||||||
views?.let { views ->
|
maybeViews?.let { views ->
|
||||||
params?.let { params ->
|
maybeParams?.let { params ->
|
||||||
if (views.size == params.size) {
|
if (views.size == params.size) {
|
||||||
for (i in views.indices) {
|
for (i in views.indices) {
|
||||||
val view = views[i]
|
val view = views[i]
|
||||||
@@ -174,16 +177,15 @@ class RootViewResolver {
|
|||||||
val getMethod = clazz.getMethod(instanceMethod)
|
val getMethod = clazz.getMethod(instanceMethod)
|
||||||
windowManagerObj = getMethod.invoke(null)
|
windowManagerObj = getMethod.invoke(null)
|
||||||
viewsField = clazz.getDeclaredField(VIEWS_FIELD)
|
viewsField = clazz.getDeclaredField(VIEWS_FIELD)
|
||||||
viewsField?.let { vf -> vf.setAccessible(true) }
|
viewsField?.let { vf -> vf.isAccessible = true }
|
||||||
paramsField = clazz.getDeclaredField(WINDOW_PARAMS_FIELD)
|
paramsField = clazz.getDeclaredField(WINDOW_PARAMS_FIELD)
|
||||||
paramsField?.let { pf -> pf.setAccessible(true) }
|
paramsField?.let { pf -> pf.isAccessible = true }
|
||||||
} catch (ite: InvocationTargetException) {} catch (cnfe: ClassNotFoundException) {} catch (
|
} catch (ite: InvocationTargetException) {} catch (cnfe: ClassNotFoundException) {} catch (
|
||||||
nsfe: NoSuchFieldException) {} catch (nsme: NoSuchMethodException) {} catch (
|
nsfe: NoSuchFieldException) {} catch (nsme: NoSuchMethodException) {} catch (
|
||||||
re: RuntimeException) {} catch (iae: IllegalAccessException) {}
|
re: RuntimeException) {} catch (iae: IllegalAccessException) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val TAG = RootViewResolver::class.java.simpleName
|
|
||||||
private const val WINDOW_MANAGER_IMPL_CLAZZ = "android.view.WindowManagerImpl"
|
private const val WINDOW_MANAGER_IMPL_CLAZZ = "android.view.WindowManagerImpl"
|
||||||
private const val WINDOW_MANAGER_GLOBAL_CLAZZ = "android.view.WindowManagerGlobal"
|
private const val WINDOW_MANAGER_GLOBAL_CLAZZ = "android.view.WindowManagerGlobal"
|
||||||
private const val VIEWS_FIELD = "mViews"
|
private const val VIEWS_FIELD = "mViews"
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ class DescriptorRegister {
|
|||||||
mapping.register(android.app.Fragment::class.java, FragmentFrameworkDescriptor)
|
mapping.register(android.app.Fragment::class.java, FragmentFrameworkDescriptor)
|
||||||
mapping.register(androidx.fragment.app.Fragment::class.java, FragmentSupportDescriptor)
|
mapping.register(androidx.fragment.app.Fragment::class.java, FragmentSupportDescriptor)
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("unchecked_cast")
|
||||||
for (clazz in mapping.register.keys) {
|
for (clazz in mapping.register.keys) {
|
||||||
val maybeDescriptor: NodeDescriptor<*>? = mapping.register[clazz]
|
val maybeDescriptor: NodeDescriptor<*>? = mapping.register[clazz]
|
||||||
maybeDescriptor?.let { descriptor ->
|
maybeDescriptor?.let { descriptor ->
|
||||||
@@ -69,7 +69,7 @@ class DescriptorRegister {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return if (register[clazz] != null) {
|
return if (register[clazz] != null) {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("unchecked_cast")
|
||||||
register[clazz] as NodeDescriptor<T>
|
register[clazz] as NodeDescriptor<T>
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ package com.facebook.flipper.plugins.uidebugger.descriptors
|
|||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.graphics.drawable.ColorDrawable
|
import android.graphics.drawable.ColorDrawable
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
|
import android.os.Build
|
||||||
import android.util.SparseArray
|
import android.util.SparseArray
|
||||||
import android.view.Gravity
|
import android.view.Gravity
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@@ -23,7 +24,6 @@ import com.facebook.flipper.plugins.uidebugger.common.InspectableValue
|
|||||||
import com.facebook.flipper.plugins.uidebugger.stetho.ResourcesUtil
|
import com.facebook.flipper.plugins.uidebugger.stetho.ResourcesUtil
|
||||||
import java.lang.reflect.Field
|
import java.lang.reflect.Field
|
||||||
|
|
||||||
@SuppressLint("DiscouragedPrivateApi")
|
|
||||||
object ViewDescriptor : ChainedDescriptor<View>() {
|
object ViewDescriptor : ChainedDescriptor<View>() {
|
||||||
|
|
||||||
override fun onGetId(node: View): String {
|
override fun onGetId(node: View): String {
|
||||||
@@ -167,6 +167,7 @@ object ViewDescriptor : ChainedDescriptor<View>() {
|
|||||||
"MATCH_PARENT" to ViewGroup.LayoutParams.MATCH_PARENT,
|
"MATCH_PARENT" to ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
"FILL_PARENT" to ViewGroup.LayoutParams.FILL_PARENT,
|
"FILL_PARENT" to ViewGroup.LayoutParams.FILL_PARENT,
|
||||||
)) {}
|
)) {}
|
||||||
|
|
||||||
private val VisibilityMapping: EnumMapping<Int> =
|
private val VisibilityMapping: EnumMapping<Int> =
|
||||||
object :
|
object :
|
||||||
EnumMapping<Int>(
|
EnumMapping<Int>(
|
||||||
@@ -177,6 +178,8 @@ object ViewDescriptor : ChainedDescriptor<View>() {
|
|||||||
)) {}
|
)) {}
|
||||||
|
|
||||||
private val LayoutDirectionMapping: EnumMapping<Int> =
|
private val LayoutDirectionMapping: EnumMapping<Int> =
|
||||||
|
when {
|
||||||
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 -> {
|
||||||
object :
|
object :
|
||||||
EnumMapping<Int>(
|
EnumMapping<Int>(
|
||||||
mapOf(
|
mapOf(
|
||||||
@@ -185,8 +188,27 @@ object ViewDescriptor : ChainedDescriptor<View>() {
|
|||||||
"LAYOUT_DIRECTION_LTR" to View.LAYOUT_DIRECTION_LTR,
|
"LAYOUT_DIRECTION_LTR" to View.LAYOUT_DIRECTION_LTR,
|
||||||
"LAYOUT_DIRECTION_RTL" to View.LAYOUT_DIRECTION_RTL,
|
"LAYOUT_DIRECTION_RTL" to View.LAYOUT_DIRECTION_RTL,
|
||||||
)) {}
|
)) {}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
object : EnumMapping<Int>(emptyMap()) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private val TextDirectionMapping: EnumMapping<Int> =
|
private val TextDirectionMapping: EnumMapping<Int> =
|
||||||
|
when {
|
||||||
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 -> {
|
||||||
|
object :
|
||||||
|
EnumMapping<Int>(
|
||||||
|
mapOf(
|
||||||
|
"TEXT_DIRECTION_INHERIT" to View.TEXT_DIRECTION_INHERIT,
|
||||||
|
"TEXT_DIRECTION_FIRST_STRONG" to View.TEXT_DIRECTION_FIRST_STRONG,
|
||||||
|
"TEXT_DIRECTION_ANY_RTL" to View.TEXT_DIRECTION_ANY_RTL,
|
||||||
|
"TEXT_DIRECTION_LTR" to View.TEXT_DIRECTION_LTR,
|
||||||
|
"TEXT_DIRECTION_RTL" to View.TEXT_DIRECTION_RTL,
|
||||||
|
"TEXT_DIRECTION_LOCALE" to View.TEXT_DIRECTION_LOCALE,
|
||||||
|
)) {}
|
||||||
|
}
|
||||||
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> {
|
||||||
object :
|
object :
|
||||||
EnumMapping<Int>(
|
EnumMapping<Int>(
|
||||||
mapOf(
|
mapOf(
|
||||||
@@ -199,8 +221,15 @@ object ViewDescriptor : ChainedDescriptor<View>() {
|
|||||||
"TEXT_DIRECTION_FIRST_STRONG_LTR" to View.TEXT_DIRECTION_FIRST_STRONG_LTR,
|
"TEXT_DIRECTION_FIRST_STRONG_LTR" to View.TEXT_DIRECTION_FIRST_STRONG_LTR,
|
||||||
"TEXT_DIRECTION_FIRST_STRONG_RTL" to View.TEXT_DIRECTION_FIRST_STRONG_RTL,
|
"TEXT_DIRECTION_FIRST_STRONG_RTL" to View.TEXT_DIRECTION_FIRST_STRONG_RTL,
|
||||||
)) {}
|
)) {}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
object : EnumMapping<Int>(emptyMap()) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private val TextAlignmentMapping: EnumMapping<Int> =
|
private val TextAlignmentMapping: EnumMapping<Int> =
|
||||||
|
when {
|
||||||
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 -> {
|
||||||
object :
|
object :
|
||||||
EnumMapping<Int>(
|
EnumMapping<Int>(
|
||||||
mapOf(
|
mapOf(
|
||||||
@@ -212,6 +241,11 @@ object ViewDescriptor : ChainedDescriptor<View>() {
|
|||||||
"TEXT_ALIGNMENT_VIEW_START" to View.TEXT_ALIGNMENT_VIEW_START,
|
"TEXT_ALIGNMENT_VIEW_START" to View.TEXT_ALIGNMENT_VIEW_START,
|
||||||
"TEXT_ALIGNMENT_VIEW_END" to View.TEXT_ALIGNMENT_VIEW_END,
|
"TEXT_ALIGNMENT_VIEW_END" to View.TEXT_ALIGNMENT_VIEW_END,
|
||||||
)) {}
|
)) {}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
object : EnumMapping<Int>(emptyMap()) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private val GravityMapping =
|
private val GravityMapping =
|
||||||
object :
|
object :
|
||||||
@@ -235,8 +269,10 @@ object ViewDescriptor : ChainedDescriptor<View>() {
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
try {
|
try {
|
||||||
|
@SuppressLint("DiscouragedPrivateApi")
|
||||||
KeyedTagsField = View::class.java.getDeclaredField("mKeyedTags")
|
KeyedTagsField = View::class.java.getDeclaredField("mKeyedTags")
|
||||||
KeyedTagsField?.let { field -> field.isAccessible = true }
|
KeyedTagsField?.let { field -> field.isAccessible = true }
|
||||||
|
@SuppressLint("DiscouragedPrivateApi")
|
||||||
ListenerInfoField = View::class.java.getDeclaredField("mListenerInfo")
|
ListenerInfoField = View::class.java.getDeclaredField("mListenerInfo")
|
||||||
ListenerInfoField?.let { field -> field.isAccessible = true }
|
ListenerInfoField?.let { field -> field.isAccessible = true }
|
||||||
val viewInfoClassName = View::class.java.name + "\$ListenerInfo"
|
val viewInfoClassName = View::class.java.name + "\$ListenerInfo"
|
||||||
|
|||||||
@@ -14,15 +14,16 @@ import com.facebook.flipper.plugins.uidebugger.descriptors.NodeDescriptor
|
|||||||
import com.facebook.flipper.plugins.uidebugger.model.Node
|
import com.facebook.flipper.plugins.uidebugger.model.Node
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This will traverse the layout hierarchy untill it sees a node that has an observer registered for
|
* This will traverse the layout hierarchy until it sees a node that has an observer registered for
|
||||||
* it. The first item in the pair is the visited nodes The second item are any observable roots
|
* it. The first item in the pair is the visited nodes The second item are any observable roots
|
||||||
* discovered
|
* discovered
|
||||||
*/
|
*/
|
||||||
class PartialLayoutTraversal(
|
class PartialLayoutTraversal(
|
||||||
private val descriptorRegister: DescriptorRegister,
|
private val descriptorRegister: DescriptorRegister,
|
||||||
private val treeObserverfactory: TreeObserverFactory,
|
private val treeObserverFactory: TreeObserverFactory,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
internal fun NodeDescriptor<*>.asAny(): NodeDescriptor<Any> = this as NodeDescriptor<Any>
|
internal fun NodeDescriptor<*>.asAny(): NodeDescriptor<Any> = this as NodeDescriptor<Any>
|
||||||
|
|
||||||
fun traverse(root: Any): Pair<MutableList<Node>, List<Any>> {
|
fun traverse(root: Any): Pair<MutableList<Node>, List<Any>> {
|
||||||
@@ -37,9 +38,8 @@ class PartialLayoutTraversal(
|
|||||||
val node = stack.removeLast()
|
val node = stack.removeLast()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// If we encounter a node that has it own observer, don't traverse
|
||||||
// if we encounter a node that has it own observer, dont traverse
|
if (node != root && treeObserverFactory.hasObserverFor(node)) {
|
||||||
if (node != root && treeObserverfactory.hasObserverFor(node)) {
|
|
||||||
observableRoots.add(node)
|
observableRoots.add(node)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -52,12 +52,12 @@ class PartialLayoutTraversal(
|
|||||||
val activeChild = descriptor.getActiveChild(node)
|
val activeChild = descriptor.getActiveChild(node)
|
||||||
|
|
||||||
for (child in children) {
|
for (child in children) {
|
||||||
// it might make sense one day to remove id from the descriptor since its always the
|
// It might make sense one day to remove id from the descriptor since its always the
|
||||||
// hash code
|
// hash code
|
||||||
val childDescriptor =
|
val childDescriptor =
|
||||||
descriptorRegister.descriptorForClassUnsafe(child::class.java).asAny()
|
descriptorRegister.descriptorForClassUnsafe(child::class.java).asAny()
|
||||||
childrenIds.add(childDescriptor.getId(child))
|
childrenIds.add(childDescriptor.getId(child))
|
||||||
// if there is an active child then dont traverse it
|
// If there is an active child then don't traverse it
|
||||||
if (activeChild == null) {
|
if (activeChild == null) {
|
||||||
stack.add(child)
|
stack.add(child)
|
||||||
}
|
}
|
||||||
@@ -79,7 +79,7 @@ class PartialLayoutTraversal(
|
|||||||
childrenIds,
|
childrenIds,
|
||||||
activeChildId))
|
activeChildId))
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
Log.e(LogTag, "Error while processing node ${node.javaClass.name} ${node} ", exception)
|
Log.e(LogTag, "Error while processing node ${node.javaClass.name} $node", exception)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ abstract class TreeObserver<T> {
|
|||||||
val start = System.currentTimeMillis()
|
val start = System.currentTimeMillis()
|
||||||
val (visitedNodes, observerRootsNodes) = context.layoutTraversal.traverse(root)
|
val (visitedNodes, observerRootsNodes) = context.layoutTraversal.traverse(root)
|
||||||
|
|
||||||
// Add any new Observers
|
// Add any new observers
|
||||||
for (observerRoot in observerRootsNodes) {
|
for (observerRoot in observerRootsNodes) {
|
||||||
|
|
||||||
if (!children.containsKey(observerRoot.identityHashCode())) {
|
if (!children.containsKey(observerRoot.identityHashCode())) {
|
||||||
@@ -55,7 +55,7 @@ abstract class TreeObserver<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove any old observers
|
// Remove any old observers
|
||||||
val observerRootIds = observerRootsNodes.map { it.identityHashCode() }
|
val observerRootIds = observerRootsNodes.map { it.identityHashCode() }
|
||||||
for (childKey in children.keys) {
|
for (childKey in children.keys) {
|
||||||
if (!observerRootIds.contains(childKey)) {
|
if (!observerRootIds.contains(childKey)) {
|
||||||
@@ -68,7 +68,6 @@ abstract class TreeObserver<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// send
|
|
||||||
Log.d(LogTag, "For Observer ${this.type} Sending ${visitedNodes.size} ")
|
Log.d(LogTag, "For Observer ${this.type} Sending ${visitedNodes.size} ")
|
||||||
context.treeObserverManager.send(
|
context.treeObserverManager.send(
|
||||||
SubtreeUpdate(type, visitedNodes, start, System.currentTimeMillis()))
|
SubtreeUpdate(type, visitedNodes, start, System.currentTimeMillis()))
|
||||||
|
|||||||
Reference in New Issue
Block a user