Skip to content

Commit 85664df

Browse files
authored
[Fragment] Replace bind with setOutput function. (#319)
* [Fragment] Replace bind with setOutput function. * Remove extra line.
1 parent 70f0258 commit 85664df

File tree

5 files changed

+57
-103
lines changed

5 files changed

+57
-103
lines changed

formula-android-compose/src/main/java/com/instacart/formula/android/compose/ComposeViewFactory.kt

+9-25
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,29 @@
11
package com.instacart.formula.android.compose
22

3-
import android.os.SystemClock
43
import android.view.LayoutInflater
54
import android.view.ViewGroup
65
import androidx.compose.runtime.Composable
76
import androidx.compose.runtime.rxjava3.subscribeAsState
87
import androidx.compose.ui.platform.ComposeView
98
import com.instacart.formula.android.FeatureView
109
import com.instacart.formula.android.ViewFactory
10+
import com.jakewharton.rxrelay3.BehaviorRelay
1111

1212

1313
abstract class ComposeViewFactory<RenderModel> : ViewFactory<RenderModel> {
1414

1515
override fun create(inflater: LayoutInflater, container: ViewGroup?): FeatureView<RenderModel> {
1616
val view = ComposeView(inflater.context)
17-
var firstRender = true
17+
val outputRelay = BehaviorRelay.create<RenderModel>()
18+
view.setContent {
19+
val model = outputRelay.subscribeAsState(null).value
20+
if (model != null) {
21+
Content(model)
22+
}
23+
}
1824
return FeatureView(
1925
view = view,
20-
bind = { state ->
21-
view.setContent {
22-
val model = state.observable.subscribeAsState(null).value
23-
if (model != null) {
24-
val start = SystemClock.uptimeMillis()
25-
Content(model)
26-
val end = SystemClock.uptimeMillis()
27-
state.environment.eventListener?.onRendered(
28-
fragmentId = state.fragmentId,
29-
durationInMillis = end - start,
30-
)
31-
32-
if (firstRender) {
33-
firstRender = false
34-
state.environment.eventListener?.onFirstModelRendered(
35-
fragmentId = state.fragmentId,
36-
durationInMillis = end - state.initializedAtMillis,
37-
)
38-
}
39-
}
40-
}
41-
null
42-
}
26+
setOutput = outputRelay::accept,
4327
)
4428
}
4529

formula-android/src/main/java/com/instacart/formula/android/FeatureView.kt

+3-10
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,11 @@ import io.reactivex.rxjava3.core.Observable
1313
* [FeatureView].
1414
*
1515
* @param view The root Android view.
16-
* @param bind A bind function connects state observable to the view rendering.
16+
* @param setOutput A function called to apply [RenderModel] to the view.
1717
* @param lifecycleCallbacks Optional lifecycle callbacks if you need to know the Fragment state.
1818
*/
1919
class FeatureView<RenderModel>(
2020
val view: View,
21-
val bind: (State<RenderModel>) -> Cancelable?,
21+
val setOutput: (RenderModel) -> Unit,
2222
val lifecycleCallbacks: FragmentLifecycleCallback? = null,
23-
) {
24-
class State<RenderModel>(
25-
val initializedAtMillis: Long,
26-
val fragmentId: FragmentId,
27-
val environment: FragmentEnvironment,
28-
val observable: Observable<RenderModel>,
29-
)
30-
}
23+
)

formula-android/src/main/java/com/instacart/formula/android/FormulaFragment.kt

+44-24
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@ import android.view.LayoutInflater
77
import android.view.View
88
import android.view.ViewGroup
99
import androidx.fragment.app.Fragment
10-
import com.instacart.formula.Cancelable
1110
import com.instacart.formula.android.internal.FormulaFragmentDelegate
1211
import com.instacart.formula.android.internal.getFormulaFragmentId
13-
import com.jakewharton.rxrelay3.BehaviorRelay
12+
import java.lang.Exception
1413

1514
class FormulaFragment : Fragment(), BaseFormulaFragment<Any> {
1615
companion object {
@@ -31,13 +30,14 @@ class FormulaFragment : Fragment(), BaseFormulaFragment<Any> {
3130
requireArguments().getParcelable<FragmentKey>(ARG_CONTRACT)!!
3231
}
3332

34-
private var initializedAtMillis: Long? = SystemClock.uptimeMillis()
35-
3633
private var featureView: FeatureView<Any>? = null
37-
private val stateRelay: BehaviorRelay<Any> = BehaviorRelay.create()
38-
private var cancelable: Cancelable? = null
34+
private var output: Any? = null
3935

40-
private var lifecycleCallback: FragmentLifecycleCallback? = null
36+
private var initializedAtMillis: Long? = SystemClock.uptimeMillis()
37+
private var firstRender = true
38+
39+
private val lifecycleCallback: FragmentLifecycleCallback?
40+
get() = featureView?.lifecycleCallbacks
4141

4242
override fun onAttach(context: Context) {
4343
super.onAttach(context)
@@ -47,6 +47,8 @@ class FormulaFragment : Fragment(), BaseFormulaFragment<Any> {
4747
}
4848

4949
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
50+
firstRender = true
51+
5052
val viewFactory = FormulaFragmentDelegate.viewFactory(this) ?: run {
5153
// No view factory, no view
5254
return null
@@ -59,17 +61,9 @@ class FormulaFragment : Fragment(), BaseFormulaFragment<Any> {
5961

6062
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
6163
super.onViewCreated(view, savedInstanceState)
62-
featureView?.let { value ->
63-
val state = FeatureView.State(
64-
initializedAtMillis = initializedAtMillis ?: SystemClock.uptimeMillis(),
65-
fragmentId = getFormulaFragmentId(),
66-
environment = FormulaFragmentDelegate.fragmentEnvironment(),
67-
observable = stateRelay,
68-
)
69-
cancelable = value.bind(state)
70-
this.lifecycleCallback = value.lifecycleCallbacks
71-
lifecycleCallback?.onViewCreated(view, savedInstanceState)
72-
}
64+
tryToSetState()
65+
66+
lifecycleCallback?.onViewCreated(view, savedInstanceState)
7367
}
7468

7569
override fun onActivityCreated(savedInstanceState: Bundle?) {
@@ -110,21 +104,18 @@ class FormulaFragment : Fragment(), BaseFormulaFragment<Any> {
110104
override fun onDestroyView() {
111105
initializedAtMillis = null
112106

113-
cancelable?.cancel()
114-
cancelable = null
115-
116107
lifecycleCallback?.onDestroyView()
117-
lifecycleCallback = null
118108
super.onDestroyView()
119109
featureView = null
120110
}
121111

122112
override fun setState(state: Any) {
123-
stateRelay.accept(state)
113+
output = state
114+
tryToSetState()
124115
}
125116

126117
override fun currentState(): Any? {
127-
return stateRelay.value
118+
return output
128119
}
129120

130121
override fun getFragmentKey(): FragmentKey {
@@ -134,4 +125,33 @@ class FormulaFragment : Fragment(), BaseFormulaFragment<Any> {
134125
override fun toString(): String {
135126
return "${key.tag} -> $key"
136127
}
128+
129+
private fun tryToSetState() {
130+
val output = output ?: return
131+
val view = featureView ?: return
132+
133+
val fragmentId = getFormulaFragmentId()
134+
val environment = FormulaFragmentDelegate.fragmentEnvironment()
135+
136+
try {
137+
val start = SystemClock.uptimeMillis()
138+
view.setOutput(output)
139+
val end = SystemClock.uptimeMillis()
140+
141+
environment.eventListener?.onRendered(
142+
fragmentId = fragmentId,
143+
durationInMillis = end - start,
144+
)
145+
146+
if (firstRender) {
147+
firstRender = false
148+
environment.eventListener?.onFirstModelRendered(
149+
fragmentId = fragmentId,
150+
durationInMillis = end - (initializedAtMillis ?: SystemClock.uptimeMillis()),
151+
)
152+
}
153+
} catch (exception: Exception) {
154+
environment.onScreenError(key, exception)
155+
}
156+
}
137157
}

formula-android/src/main/java/com/instacart/formula/android/ViewInstance.kt

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package com.instacart.formula.android
33
import android.view.View
44
import com.instacart.formula.RenderView
55
import com.instacart.formula.Renderer
6-
import com.instacart.formula.android.views.FeatureViewBindFunction
76

87
/**
98
* View instance contains an initialized Android [view] and provides factory
@@ -37,7 +36,7 @@ abstract class ViewInstance {
3736
): FeatureView<RenderModel> {
3837
return FeatureView(
3938
view = view,
40-
bind = FeatureViewBindFunction(renderer),
39+
setOutput = renderer,
4140
lifecycleCallbacks = lifecycleCallbacks
4241
)
4342
}

formula-android/src/main/java/com/instacart/formula/android/views/FeatureViewBindFunction.kt

-42
This file was deleted.

0 commit comments

Comments
 (0)