This repository has been archived by the owner on Nov 22, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 958
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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
- Loading branch information
1 parent
c861b3a
commit dc28e2a
Showing
2 changed files
with
165 additions
and
0 deletions.
There are no files selected for viewing
66 changes: 66 additions & 0 deletions
66
android/src/main/java/com/facebook/flipper/plugins/uidebugger/core/ApplicationInspector.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
} | ||
} | ||
} | ||
} |
99 changes: 99 additions & 0 deletions
99
android/src/main/java/com/facebook/flipper/plugins/uidebugger/core/ApplicationRef.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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>>() | ||
} | ||
} |