ApplicationRef
Summary: Introduce ApplicationRef which holds a reference to Application. It exposes a few utility methods to get view roots and activities. ApplicationInspector has a few template methods for useful things which are not used in this diff and most likely will either be moved/deleted/changed on the final implementation. Reviewed By: LukeDefeo Differential Revision: D38829523 fbshipit-source-id: b8aeb133dceb3af42b5f7d6851ef531d35fc7d69
This commit is contained in:
committed by
Facebook GitHub Bot
parent
c861b3af4d
commit
dc28e2ad45
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* 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.core
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewTreeObserver
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.commands.Context
|
||||||
|
import java.util.List
|
||||||
|
|
||||||
|
class ApplicationInspector(val context: Context) {
|
||||||
|
|
||||||
|
fun traverse(view: View) {
|
||||||
|
val inspector =
|
||||||
|
LayoutVisitor.create(
|
||||||
|
object : LayoutVisitor.Visitor {
|
||||||
|
override fun visit(view: View) {}
|
||||||
|
})
|
||||||
|
inspector.traverse(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun attachListeners(view: View) {
|
||||||
|
// An OnGlobalLayoutListener watches the entire hierarchy for layout changes
|
||||||
|
// (so registering one of these on any View in a hierarchy will cause it to be triggered
|
||||||
|
// when any View in that hierarchy is laid out or changes visibility).
|
||||||
|
view
|
||||||
|
.getViewTreeObserver()
|
||||||
|
.addOnGlobalLayoutListener(
|
||||||
|
object : ViewTreeObserver.OnGlobalLayoutListener {
|
||||||
|
override fun onGlobalLayout() {}
|
||||||
|
})
|
||||||
|
view
|
||||||
|
.getViewTreeObserver()
|
||||||
|
.addOnPreDrawListener(
|
||||||
|
object : ViewTreeObserver.OnPreDrawListener {
|
||||||
|
override fun onPreDraw(): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun observe() {
|
||||||
|
val rootResolver = RootViewResolver()
|
||||||
|
rootResolver.attachListener(
|
||||||
|
object : RootViewResolver.Listener {
|
||||||
|
override fun onRootViewAdded(view: View) {
|
||||||
|
attachListeners(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRootViewRemoved(view: View) {}
|
||||||
|
|
||||||
|
override fun onRootViewsChanged(views: List<View>) {}
|
||||||
|
})
|
||||||
|
|
||||||
|
val activeRoots = rootResolver.listActiveRootViews()
|
||||||
|
activeRoots?.let { roots ->
|
||||||
|
for (root: RootViewResolver.RootView in roots) {
|
||||||
|
traverse(root.view)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* 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.core
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.app.Application
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.View
|
||||||
|
import java.lang.ref.WeakReference
|
||||||
|
|
||||||
|
class ApplicationRef(val application: Application) : Application.ActivityLifecycleCallbacks {
|
||||||
|
interface ActivityStackChangedListener {
|
||||||
|
fun onActivityStackChanged(stack: List<Activity>)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ActivityDestroyedListener {
|
||||||
|
fun onActivityDestroyed(activity: Activity)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val rootsResolver: RootViewResolver
|
||||||
|
private val activities: MutableList<WeakReference<Activity>>
|
||||||
|
private var activityStackChangedlistener: ActivityStackChangedListener? = null
|
||||||
|
private var activityDestroyedListener: ActivityDestroyedListener? = null
|
||||||
|
|
||||||
|
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
|
||||||
|
activities.add(WeakReference<Activity>(activity))
|
||||||
|
activityStackChangedlistener?.let { listener ->
|
||||||
|
listener.onActivityStackChanged(this.activitiesStack)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
override fun onActivityStarted(activity: Activity) {}
|
||||||
|
override fun onActivityResumed(activity: Activity) {}
|
||||||
|
override fun onActivityPaused(activity: Activity) {}
|
||||||
|
override fun onActivityStopped(activity: Activity) {}
|
||||||
|
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
|
||||||
|
override fun onActivityDestroyed(activity: Activity) {
|
||||||
|
val activityIterator: MutableIterator<WeakReference<Activity>> = activities.iterator()
|
||||||
|
|
||||||
|
while (activityIterator.hasNext()) {
|
||||||
|
if (activityIterator.next().get() === activity) {
|
||||||
|
activityIterator.remove()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
activityDestroyedListener?.let { listener -> listener.onActivityDestroyed(activity) }
|
||||||
|
|
||||||
|
activityStackChangedlistener?.let { listener ->
|
||||||
|
listener.onActivityStackChanged(this.activitiesStack)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setActivityStackChangedListener(listener: ActivityStackChangedListener?) {
|
||||||
|
activityStackChangedlistener = listener
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setActivityDestroyedListener(listener: ActivityDestroyedListener?) {
|
||||||
|
activityDestroyedListener = listener
|
||||||
|
}
|
||||||
|
|
||||||
|
val activitiesStack: List<Activity>
|
||||||
|
get() {
|
||||||
|
val stack: MutableList<Activity> = ArrayList<Activity>(activities.size)
|
||||||
|
val activityIterator: MutableIterator<WeakReference<Activity>> = activities.iterator()
|
||||||
|
while (activityIterator.hasNext()) {
|
||||||
|
val activity: Activity? = activityIterator.next().get()
|
||||||
|
if (activity == null) {
|
||||||
|
activityIterator.remove()
|
||||||
|
} else {
|
||||||
|
stack.add(activity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stack
|
||||||
|
}
|
||||||
|
|
||||||
|
val rootViews: List<View>
|
||||||
|
get() {
|
||||||
|
val roots = rootsResolver.listActiveRootViews()
|
||||||
|
roots?.let { roots ->
|
||||||
|
val viewRoots: MutableList<View> = ArrayList<View>(roots.size)
|
||||||
|
for (root in roots) {
|
||||||
|
viewRoots.add(root.view)
|
||||||
|
}
|
||||||
|
return viewRoots
|
||||||
|
}
|
||||||
|
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
rootsResolver = RootViewResolver()
|
||||||
|
application.registerActivityLifecycleCallbacks(this)
|
||||||
|
activities = ArrayList<WeakReference<Activity>>()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user