Introduced concept of active child
Summary: A node can have an active child, if present we assume all others are inactive and we don't traverse them. This means the activities not on top and view pager views not active will not be scanned. Additionally on the desktop we are automatically collapsing these views. The net result is a lot less work done on the main thread Reviewed By: lblasa Differential Revision: D39310126 fbshipit-source-id: ebd0c69d46f2d42fe42e678c8327fcdc73d08385
This commit is contained in:
committed by
Facebook GitHub Bot
parent
a9fe381076
commit
c76c993ce4
@@ -40,19 +40,37 @@ class LayoutTraversal(
|
||||
descriptor.getChildren(node, children)
|
||||
|
||||
val childrenIds = mutableListOf<String>()
|
||||
|
||||
val activeChild = descriptor.getActiveChild(node)
|
||||
for (child in children) {
|
||||
// it might make sense one day to remove id from the descriptor since its always the
|
||||
// hash code
|
||||
val childDescriptor =
|
||||
descriptorRegister.descriptorForClassUnsafe(child::class.java).asAny()
|
||||
childrenIds.add(childDescriptor.getId(child))
|
||||
stack.add(child)
|
||||
// if there is an active child then dont traverse it
|
||||
if (activeChild == null) {
|
||||
stack.add(child)
|
||||
}
|
||||
}
|
||||
|
||||
var activeChildId: String? = null
|
||||
if (activeChild != null) {
|
||||
stack.add(activeChild)
|
||||
activeChildId =
|
||||
descriptorRegister.descriptorForClassUnsafe(activeChild.javaClass).getId(activeChild)
|
||||
}
|
||||
|
||||
val attributes = mutableMapOf<String, InspectableObject>()
|
||||
descriptor.getData(node, attributes)
|
||||
|
||||
result.add(Node(descriptor.getId(node), descriptor.getName(node), attributes, childrenIds))
|
||||
result.add(
|
||||
Node(
|
||||
descriptor.getId(node),
|
||||
descriptor.getName(node),
|
||||
attributes,
|
||||
childrenIds,
|
||||
activeChildId))
|
||||
} catch (exception: Exception) {
|
||||
Log.e(LogTag, "Error while processing node ${node.javaClass.name} ${node} ", exception)
|
||||
}
|
||||
|
||||
@@ -33,13 +33,7 @@ class NativeScanScheduler(val context: Context) : Scheduler.Task<ScanResult> {
|
||||
|
||||
Log.d(
|
||||
"LAYOUT_SCHEDULER",
|
||||
Thread.currentThread().name +
|
||||
Looper.myLooper() +
|
||||
", produced: " +
|
||||
{
|
||||
nodes.count()
|
||||
} +
|
||||
" nodes")
|
||||
"${Thread.currentThread().name}${Looper.myLooper()} produced: ${nodes.count()} nodes")
|
||||
|
||||
return ScanResult(txId++, start, scanEnd, nodes)
|
||||
}
|
||||
|
||||
@@ -34,6 +34,12 @@ abstract class AbstractChainedDescriptor<T> : Descriptor<T>(), ChainedDescriptor
|
||||
|
||||
open fun onInit() {}
|
||||
|
||||
final override fun getActiveChild(node: T): Any? {
|
||||
// ask each descriptor in the chain for an active child, if none available look up the chain
|
||||
// until no more super descriptors
|
||||
return onGetActiveChild(node) ?: mSuper?.getActiveChild(node)
|
||||
}
|
||||
|
||||
/**
|
||||
* A globally unique ID used to identify a node in a hierarchy. If your node does not have a
|
||||
* globally unique ID it is fine to rely on [System.identityHashCode].
|
||||
@@ -52,6 +58,8 @@ abstract class AbstractChainedDescriptor<T> : Descriptor<T>(), ChainedDescriptor
|
||||
return onGetName(node)
|
||||
}
|
||||
|
||||
abstract fun onGetActiveChild(node: T): Any?
|
||||
|
||||
abstract fun onGetName(node: T): String
|
||||
|
||||
/** The children this node exposes in the inspector. */
|
||||
|
||||
@@ -13,6 +13,9 @@ import com.facebook.flipper.plugins.uidebugger.stetho.FragmentCompat
|
||||
|
||||
class ActivityDescriptor : AbstractChainedDescriptor<Activity>() {
|
||||
override fun onInit() {}
|
||||
override fun onGetActiveChild(node: Activity): Any? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun onGetId(activity: Activity): String {
|
||||
return Integer.toString(System.identityHashCode(activity))
|
||||
|
||||
@@ -16,6 +16,9 @@ class ApplicationRefDescriptor : AbstractChainedDescriptor<ApplicationRef>() {
|
||||
val rootResolver = RootViewResolver()
|
||||
|
||||
override fun onInit() {}
|
||||
override fun onGetActiveChild(node: ApplicationRef): Any? {
|
||||
return if (node.activitiesStack.size > 0) node.activitiesStack.last() else null
|
||||
}
|
||||
|
||||
override fun onGetId(applicationRef: ApplicationRef): String {
|
||||
return applicationRef.application.packageName
|
||||
@@ -38,7 +41,6 @@ class ApplicationRefDescriptor : AbstractChainedDescriptor<ApplicationRef>() {
|
||||
if (activity.window.decorView == root.view) {
|
||||
children.add(activity)
|
||||
added = true
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,4 +26,7 @@ class ButtonDescriptor : AbstractChainedDescriptor<Button>() {
|
||||
) {}
|
||||
|
||||
override fun onGetChildren(button: Button, children: MutableList<Any>) {}
|
||||
override fun onGetActiveChild(node: Button): Any? {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,31 +26,4 @@ abstract class Descriptor<T> : NodeDescriptor<T> {
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
// override fun inspect(obj: Any): FlipperObject {
|
||||
// val descriptor = descriptorForObject(obj)
|
||||
// descriptor?.let { descriptor ->
|
||||
// return (descriptor as Descriptor<Any>).get(obj)
|
||||
// }
|
||||
//
|
||||
// return FlipperObject.Builder().build()
|
||||
// }
|
||||
//
|
||||
// override fun get(node: T): FlipperObject {
|
||||
// val builder = FlipperObject.Builder()
|
||||
//
|
||||
// val propsBuilder = FlipperObject.Builder()
|
||||
// getData(node, propsBuilder)
|
||||
//
|
||||
// val childrenBuilder = FlipperArray.Builder()
|
||||
// getChildren(node, childrenBuilder)
|
||||
//
|
||||
// builder
|
||||
// .put("key", getId(node))
|
||||
// .put("title", getName(node))
|
||||
// .put("data", propsBuilder)
|
||||
// .put("children", childrenBuilder)
|
||||
//
|
||||
// return builder.build()
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import android.view.ViewGroup
|
||||
import android.view.Window
|
||||
import android.widget.Button
|
||||
import android.widget.TextView
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import com.facebook.flipper.plugins.uidebugger.common.UIDebuggerException
|
||||
import com.facebook.flipper.plugins.uidebugger.core.ApplicationRef
|
||||
|
||||
@@ -31,6 +32,7 @@ class DescriptorRegister {
|
||||
mapping.register(View::class.java, ViewDescriptor())
|
||||
mapping.register(TextView::class.java, TextViewDescriptor())
|
||||
mapping.register(Button::class.java, ButtonDescriptor())
|
||||
mapping.register(ViewPager::class.java, ViewPagerDescriptor())
|
||||
|
||||
for (clazz in mapping.register.keys) {
|
||||
val descriptor: Descriptor<*>? = mapping.register[clazz]
|
||||
|
||||
@@ -28,6 +28,12 @@ interface NodeDescriptor<T> {
|
||||
/** The children this node exposes in the inspector. */
|
||||
fun getChildren(node: T, children: MutableList<Any>)
|
||||
|
||||
/**
|
||||
* If you have overlapping children this indicates which child is active / on top, we will only
|
||||
* listen to / traverse this child. If return null we assume all children are 'active'
|
||||
*/
|
||||
fun getActiveChild(node: T): Any?
|
||||
|
||||
/**
|
||||
* Get the data to show for this node in the sidebar of the inspector. The object will be shown in
|
||||
* order and with a header matching the given name.
|
||||
|
||||
@@ -11,6 +11,9 @@ import com.facebook.flipper.plugins.uidebugger.common.InspectableObject
|
||||
|
||||
class ObjectDescriptor : Descriptor<Any>() {
|
||||
override fun init() {}
|
||||
override fun getActiveChild(node: Any): Any? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun getId(obj: Any): String {
|
||||
return Integer.toString(System.identityHashCode(obj))
|
||||
|
||||
@@ -26,4 +26,8 @@ class TextViewDescriptor : AbstractChainedDescriptor<TextView>() {
|
||||
textView: TextView,
|
||||
attributeSections: MutableMap<String, InspectableObject>
|
||||
) {}
|
||||
|
||||
override fun onGetActiveChild(node: TextView): Any? {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,4 +256,8 @@ class ViewDescriptor : AbstractChainedDescriptor<View>() {
|
||||
} catch (ignored: Exception) {}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onGetActiveChild(node: View): Any? {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,4 +85,8 @@ class ViewGroupDescriptor : AbstractChainedDescriptor<ViewGroup>() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onGetActiveChild(node: ViewGroup): Any? {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.flipper.plugins.uidebugger.descriptors
|
||||
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
|
||||
class ViewPagerDescriptor : AbstractChainedDescriptor<ViewPager>() {
|
||||
|
||||
override fun onGetId(node: ViewPager): String = System.identityHashCode(node).toString()
|
||||
|
||||
override fun onGetName(node: ViewPager): String = node.javaClass.simpleName
|
||||
|
||||
override fun onGetActiveChild(node: ViewPager): Any? = node.getChildAt(node.currentItem)
|
||||
}
|
||||
@@ -28,4 +28,8 @@ class WindowDescriptor : AbstractChainedDescriptor<Window>() {
|
||||
window: Window,
|
||||
attributeSections: MutableMap<String, InspectableObject>
|
||||
) {}
|
||||
|
||||
override fun onGetActiveChild(node: Window): Any? {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,5 +14,6 @@ data class Node(
|
||||
val id: String,
|
||||
val name: String,
|
||||
val attributes: Map<String, InspectableObject>,
|
||||
val children: List<String>
|
||||
val children: List<String>,
|
||||
val activeChild: String?,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user