Skip to content

CONCEPT Cited by 1 source

View-tree traversal

Definition

View-tree traversal is walking a hierarchical UI element tree from a root node downward to compute a derived predicate or aggregate. Nearly every modern UI toolkit exposes its UI as a tree — Android View / ViewGroup, iOS UIKit view hierarchy / SwiftUI view graph, HTML DOM, Flutter widget tree — and many cross-cutting concerns (rendering, hit-testing, accessibility, layout, instrumentation) are expressed as a tree walk.

Pinterest uses view-tree traversal as the mechanism for automatic Visually Complete detection: "at the BaseSurface level, given that we should have access to the root android ViewGroup (e.g. RootView), we could just iterate through the view tree starting from the RootView by visiting all the views on this tree." (Source: sources/2026-04-08-pinterest-performance-for-everyone).

Shape of a traversal for instrumentation

The canonical shape, following Pinterest's mechanism:

walk(rootView):
    for each view in tree(rootView):
        if not isVisible(view):
            continue
        if view implements PerfImageView or PerfTextView:
            if not view.isDrawn():
                return NOT_READY
        if view implements PerfVideoView:
            if not view.isVideoLoadStarted():
                return NOT_READY
    return READY

The predicate has four moving parts:

  1. Root node — where the walk starts (Pinterest: the Android RootView of the screen).
  2. Iteration strategy — DFS / BFS; typically DFS for deterministic ordering.
  3. Filter — which nodes contribute (Pinterest: visible-and-implements-Perf*).
  4. Reduction — how per-node results combine (Pinterest: conjunction — ALL contributing nodes must be ready).

Cost considerations

View-tree traversal is linear in tree size. On deeply-nested or view-heavy screens this can be non-trivial:

  • Android feed screens with dozens of cards × multiple images-per-card can have hundreds of View instances.
  • Repeatedly traversing on every frame would be prohibitive.
  • Traversal is typically triggered on meaningful events: view hierarchy changes, draw events, or debounced intervals.

Pinterest's post doesn't disclose the traversal cadence. In practice Android instrumentation typically hooks ViewTreeObserver.OnGlobalLayoutListener / OnPreDrawListener / Choreographer frame callbacks to scope traversal to frame boundaries.

Traversal beyond instrumentation

View-tree traversal is the substrate for many platform concerns:

  • Rendering — the framework walks the tree to compute layout + paint passes.
  • Hit-testing — map a touch coordinate to the deepest view covering it.
  • Accessibility — build the a11y tree by walking the view hierarchy.
  • Snapshot testing — serialize the tree state for diffing.
  • Screen-reader announcements — derive linear reading order from tree order.
  • Automatic analytics — derive screen content from tree state.

The instrumentation use case is in the same family: "what does the tree state tell me about a user-visible predicate?"

Across platforms

  • AndroidViewGroup.getChildAt(i) recursion; View identity via View.getId(); geometry via getX() / getY() / getWidth() / getHeight().
  • iOS UIKitUIView.subviews recursion; geometry via frame / bounds; isHidden for visibility.
  • iOS SwiftUI — opaque view graph; traversal less direct; Mirror-based reflection or preference-key bubbling for similar patterns.
  • Web DOMElement.children recursion or querySelectorAll; IntersectionObserver for visibility; getBoundingClientRect() for geometry.

Pinterest extended the base-class-Visually-Complete mechanism to iOS and Web (Source: sources/2026-04-08-pinterest-performance-for-everyone), presumably adapting the traversal mechanism to each platform's tree model.

Caveats

  • Dynamic trees — views can appear/disappear during scroll, layout pass, animations. A single-snapshot traversal can miss transient states.
  • Lazy views / recyclingRecyclerView / UICollectionView / windowed DOM virtualisation may keep views off-tree even when their content is logically visible. A "visible" filter based on geometry can miss logically-visible but not-yet-materialised content.
  • Off-screen tree residents — views can remain in the tree after going off-screen (tab navigation, modal dismissal). Geometry-based filters handle these.
  • Opaque overlays — a view can be geometrically on-screen but covered by an opaque overlay; naive geometry filters may count it as visible.

Seen in

  • 2026-04-08 Pinterest — Performance for Everyone (sources/2026-04-08-pinterest-performance-for-everyone) — canonical; traversal of Android ViewGroup tree from BaseSurface to decide Visually Complete; filter by visibility via Perf* geometry methods; conjunction over all Perf* instances.
Last updated · 319 distilled / 1,201 read