Colton Idle
01/31/2024, 5:16 AMonResume()
callback in activity and I check if a value exists from the intent. If it does, I want to send it "down" into my compose app. What's the best way to do this? I currently have this working with a MutableStateFlow, but can't I just do this with callbacks somehow?
My Android Activity and my compose app are inside the thread. About 15 lines of codeColton Idle
01/31/2024, 5:17 AMclass MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val state = MutableStateFlow("")
setContent {
App(state)
}
}
override fun onResume() {
if (intent.data.getThing != null){
state.emit(authCode)
}
super.onResume()
}
My shared App()
@Composable
fun App(callback: MutableStateFlow<String>) {
Column {
Text("Token was: ${callback.collectAsState().value}")
}
}
Colton Idle
01/31/2024, 5:18 AMColton Idle
01/31/2024, 5:32 AM@Composable
fun App(callback: (String)->Unit) {
// Can only call callback.invoke("blah") here, when what I actually want to do is call callback.invoke("blah") in my activity
Column {
Text("Token was: ${callback.collectAsState().value}")
}
}
Colton Idle
01/31/2024, 5:37 AMColton Idle
01/31/2024, 5:53 AMclass Blah {
private var callback: ((String) -> Unit)? = null
fun registerCallback(input: (String) -> Unit) {
callback = input
}
fun callCallback(input: String) {
callback?.invoke(input)
}
}
and
@Composable
fun App(blah: Blah) {
var currentToken by remember { mutableStateOf("no token") }
println("registering callback")
blah.registerCallback {
println("got callbacked")
currentToken = it
}
but "got callbackd" never gets calledPablichjenkov
01/31/2024, 6:07 AMclass Dispatcher {
callback: (String) -> Unit
// subscribe/unsubscribe functions maybe better
}
class AppState(val dispatcher: IntentDispatcher)
@Composable
fun AppCalledFromSwift(dispatcher: Dispatcher) {
val stateFlow = remember { MutableStateFlow<String>() }
DisposableEffect {
dispatcher.callback = { data ->
stateFlow.update { value = data }
}
}.onDispose {
dispatcher.callback = null
}
SharedApp(stateFlow)
}
I would prefer passing down an AppState
class that contains this interface impl rather than the StateFlow.Colton Idle
01/31/2024, 6:14 AMColton Idle
01/31/2024, 6:15 AMColton Idle
01/31/2024, 6:18 AM@Composable
fun App(dispatcher: Dispatcher) {
var currentToken by remember { mutableStateOf("no token") }
LaunchedEffect(Unit){
dispatcher.callback = { data ->
currentToken = data
}
}
... Column with text
then my android MainActivity is
class MainActivity : ComponentActivity() {
val dispatcher = Dispatcher()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
App(dispatcher)
}
with an onResume of
dispatcher.callback?.invoke("my token here")Colton Idle
01/31/2024, 6:22 AMColton Idle
01/31/2024, 6:22 AMColton Idle
01/31/2024, 6:28 AMColton Idle
01/31/2024, 6:30 AMColton Idle
01/31/2024, 6:30 AMPablichjenkov
01/31/2024, 6:53 AMinterface IntentDispatcher {
fun dispatch(data: String)
fun subscribe(callback: (String) -> Unit)
fun unsubscribe(callback: (String) -> Unit)
}
class IntentDispatcherKtImpl : IntentDispatcher {
private val _stateFlow = MutableStateFlow("")
private val corouitneScope = CorouitneScope(Disptacher.Default)
private val listeners = mutableListOf<(String) -> Unit>()
init() {
corouitneScope.launch {
_stateFlow.collect { data ->
listeners.forEach { it.invoke(data) }
}
}
}
override fun dispatch(data: String) {
_stateFlow.update { value = data }
}
override fun subscribe(callback: (String) -> Unit) {
listeners.addIfNotExist(callback)
}
override fun unsubscribe(callback: (String) -> Unit) {
listeners.remove(callback)
}
}
Then in a public kotlin file
you can expose a public factory function
that returns the implementation to swift.
Binder.kt
// Call this one from swift
fun createIntentDispatcher(): IntentDispatcher {
return IntentDispatcherKtImpl()
}
*Above can be improved in many ways. Is just a quick test throughCiaran Sloan
01/31/2024, 10:00 AMPablichjenkov
01/31/2024, 2:09 PMColton Idle
01/31/2024, 3:13 PM