Add more Routing lifecycle events to support RIB Tree tracing
Nobody has claimed this yet.
- Dominant language
- Kotlin
- Stars
- 7.9k
- Forks
- 914
- PR merge metrics
- No merged PRs in 30d
Description
We are trying to improve the overall performance of our app. The first thing we think we should do beside of manual Profiling is tracking performance for specific code.
For UIView/UIViewController, swizzle help to automatically record a trace then send to a Telemetry tracing API. We also want to do that for Interactor/Router but they are pure Swift so no swizzle at all.
We tried to do that by adding more lifecycle events for Router and Interactor like below:
Router:
/// The lifecycle stages of a router scope.
public enum RouterLifecycle {
/// Router did load.
case didLoad
/// Router will attach child
case willAttachChild(Routing)
/// Router did attach child
case didAttachChild(Routing)
/// Router will detach child
case willDetachChild(Routing)
/// Router did detach child
case didDetachChild(Routing)
}
open class Router<InteractorType>: Routing {
/// Attaches the given router as a child.
///
/// - parameter child: The child `Router` to attach.
public final func attachChild(_ child: Routing) {
assert(!(children.contains { $0 === child }), "Attempt to attach child: \(child), which is already attached to \(self).")
lifecycleSubject.onNext(.willAttachChild(child))
children.append(child)
// Activate child first before loading. Router usually attaches immutable children in didLoad.
// We need to make sure the RIB is activated before letting it attach immutable children.
child.interactable.activate()
child.load()
lifecycleSubject.onNext(.didAttachChild(child))
}
/// Detaches the given `Router` from the tree.
///
/// - parameter child: The child `Router` to detach.
public final func detachChild(_ child: Routing) {
lifecycleSubject.onNext(.willDetachChild(child))
child.interactable.deactivate()
children.removeElementByReference(child)
lifecycleSubject.onNext(.didDetachChild(child))
}
}
Then we can do recursive observe for child RIBs lifecycle to add performance trace. This enables as we can add observer only one in Root:
RootRouter:
func observeRouter(_ router: Routing) {
let didBecomeActive = router.interactable.isActiveStream.skip(1).filter { $0 == false }
let willAttachChild = router
.lifecycle
.compactMap { lifecycle -> Routing? in
if case .willAttachChild(let child) = lifecycle {
return child
} else {
return nil
}
}
.takeUntil(didBecomeActive)
let didAttachChild = router
.lifecycle
.compactMap { lifecycle -> Routing? in
if case .didAttachChild(let child) = lifecycle {
return child
} else {
return nil
}
}
.takeUntil(didBecomeActive)
_ = willAttachChild
.subscribe(onNext: { child in
/// Recursive observe child router
observeRouter(child)
})
_ = willAttachChild
.flatMap { child -> Observable<(Routing)> in
return child.interactable.isActiveStream.filter { $0 }.map { _ in return child }
}
.subscribe(onNext: { child in
/// Start Performance Tracing Interator didBecomeActive
})
_ = didAttachChild
.subscribe(onNext: { child in
/// Stop Performance Tracing here
})
}
We can simply add observer at the Root RIB and for example, use os_signpost to tracing performance in Instrument:
Adding more lifecycle event for Router also help to easier to implement a RIB Tree real-time viewer like https://github.com/srea/RIBsTreeViewerClient or https://github.com/imairi/RIBsTreeMaker
I really want to know your ideas and willing to open a PR if this will make sense to include in Uber RIBs
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the Router and Interactor lifecycle proposal and the RootRouter observeRouter example, including the attachChild and detachChild entry points. Determine whether the additional lifecycle events and recursive observation fit RIBs; done requires an agreed API and implementation scope for tracing or real-time tree viewing.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- swift
- Domain
- mobile-dev, performance
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100