Matt Nelson
05/29/2023, 10:52 AMinterface KeyComponent {
fun createKey(data: Data)
}
class DefaultKeyComponent private constructor(
context: ComponentContext,
retained: RetainedKeyComponent,
onCreated: (uuid: String) -> Unit,
): KeyComponent by retained {
constructor(
context: ComponentContext,
api: ApiKeys,
mainContext: CoroutineContext,
onCreated: (uuid: String) -> Unit,
): this(
context = context,
retained = context.instanceKeeper.getOrCreate {
RetainedKeyComponent(api, mainContext)
},
onCreated = onCreated,
)
init {
// Can't pass the lambda to navigate to retained component,
// b/c that'd be a leak, so observe key here between start/stop
val observer: (List<Key>) -> Unit = observer@ { list ->
val key = list.firstOrNull() ?: return@observer
onCreated(key.uuid)
}
context.lifecycle.subscribe(
onStart = { retained.key.subscribe(observer) },
onStop = { retained.key.unsubscribe(observer) },
)
}
}
private class RetainedKeyComponent(
private val api: ApiKeys,
mainContext: CoroutineContext,
): KeyComponent, InstanceKeeper.Instance {
private val scope = retainedScope(mainContext) // extension function on InstanceKeeper.Instance
// Uses List b/c Value Type cannot be nullable
private val _key = MutableValue<List<Key>>(emptyList())
val key: Value<List<Key>> = _keys.toValue() // extension function on MutableValue
override fun createKey(data: Data) {
// TODO
}
override fun onDestroy() {
scope.cancel()
}
}
Arkadii Ivanov
05/29/2023, 2:32 PMMatt Nelson
05/29/2023, 5:31 PMDefaultKeyComponent
, and instantiating the RetainedKeyComponent
via instanceKeeper
, you can use the retained key component as a delegate for the DefaultKeyComponent
's primary constructor.
Of coure, you do not want to pass to the retained component any contextual things such as lambdas to do navigation and what not. So it separates out the logic a bit more into properly scoped components (very much like ViewModels).Arkadii Ivanov
05/29/2023, 9:12 PMArkadii Ivanov
05/29/2023, 9:13 PM