Skip to content

Commit

Permalink
[Formula Android] Track first render.
Browse files Browse the repository at this point in the history
  • Loading branch information
Laimiux committed Nov 30, 2023
1 parent 1da9a35 commit 629884a
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,28 @@ abstract class ComposeViewFactory<RenderModel> : ViewFactory<RenderModel> {

override fun create(inflater: LayoutInflater, container: ViewGroup?): FeatureView<RenderModel> {
val view = ComposeView(inflater.context)
var firstRender = true
return FeatureView(
view = view,
bind = {
bind = { state ->
view.setContent {
val model = it.observable.subscribeAsState(null).value
val model = state.observable.subscribeAsState(null).value
if (model != null) {
val start = SystemClock.uptimeMillis()
Content(model)
val end = SystemClock.uptimeMillis()
it.environment.eventListener?.onRendered(
fragmentId = it.fragmentId,
state.environment.eventListener?.onRendered(
fragmentId = state.fragmentId,
durationInMillis = end - start,
)

if (firstRender) {
firstRender = false
state.environment.eventListener?.onFirstModelRendered(
fragmentId = state.fragmentId,
durationInMillis = end - state.initialized,
)
}
}
}
null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class FeatureView<RenderModel>(
val lifecycleCallbacks: FragmentLifecycleCallback? = null,
) {
class State<RenderModel>(
val initialized: Long,
val fragmentId: FragmentId,
val environment: FragmentEnvironment,
val observable: Observable<RenderModel>,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.instacart.formula.android

import android.os.Bundle
import android.os.SystemClock
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
Expand Down Expand Up @@ -29,6 +30,8 @@ class FormulaFragment : Fragment(), BaseFormulaFragment<Any> {
requireArguments().getParcelable<FragmentKey>(ARG_CONTRACT)!!
}

private val initialized = SystemClock.uptimeMillis()

private var featureView: FeatureView<Any>? = null
private val stateRelay: BehaviorRelay<Any> = BehaviorRelay.create()
private var cancelable: Cancelable? = null
Expand All @@ -50,6 +53,7 @@ class FormulaFragment : Fragment(), BaseFormulaFragment<Any> {
super.onViewCreated(view, savedInstanceState)
featureView?.let { value ->
val state = FeatureView.State(
initialized = initialized,
fragmentId = getFormulaFragmentId(),
environment = FormulaFragmentDelegate.fragmentEnvironment(),
observable = stateRelay,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,11 @@ data class FragmentEnvironment(
* Called after render model was applied to the [FeatureView].
*/
fun onRendered(fragmentId: FragmentId, durationInMillis: Long)

/**
* Called after first render model is rendered. The [durationInMillis] starts
* when formula fragment is initialized and ends after first render model is applied.
*/
fun onFirstModelRendered(fragmentId: FragmentId, durationInMillis: Long)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ internal class FeatureViewBindFunction<RenderModel>(
) : (FeatureView.State<RenderModel>) -> Cancelable? {
override fun invoke(state: FeatureView.State<RenderModel>): Cancelable {
val environment = state.environment
var firstRender = true
val disposable = state.observable.subscribe {
try {
val start = SystemClock.uptimeMillis()
Expand All @@ -23,6 +24,13 @@ internal class FeatureViewBindFunction<RenderModel>(
fragmentId = state.fragmentId,
durationInMillis = end - start,
)
if (firstRender) {
firstRender = false
environment.eventListener?.onFirstModelRendered(
fragmentId = state.fragmentId,
durationInMillis = end - state.initialized,
)
}
} catch (exception: Exception) {
environment.onScreenError(state.fragmentId.key, exception)
}
Expand Down

0 comments on commit 629884a

Please sign in to comment.