grandstaish
05/17/2020, 1:23 AMAdam Powell
05/17/2020, 2:17 AMTimo Drick
05/17/2020, 8:34 AMsealed class LoadingState<out T: Any> {
object Start: LoadingState<Nothing>()
object Loading : LoadingState<Nothing>()
class Error(val error: Throwable): LoadingState<Nothing>()
class Success<T: Any>(val data: T): LoadingState<T>()
}
@Composable
fun <T: Any> loadingStateFor(vararg inputs: Any?, initBlock: () -> LoadingState<T>, disposeBlock: () -> Unit = {}, loadingBlock: suspend CoroutineScope.() -> T): LoadingState<T> {
var state by stateFor(*inputs, init = initBlock)
onCommit(*inputs) {
val job = if (state !is LoadingState.Success) {
CoroutineScope(Dispatchers.Main.immediate).launch {
val loadingSpinnerDelay = async {
delay(500)
state = LoadingState.Loading
}
state = try {
LoadingState.Success(loadingBlock())
} catch (err: Throwable) {
LoadingState.Error(err)
} finally {
loadingSpinnerDelay.cancelAndJoin()
}
}
} else null
onDispose {
job?.cancel()
disposeBlock()
}
}
return state
}
grandstaish
05/17/2020, 10:54 AM@Composable
fun App() {
val (state, setState) = ...
when (state) {
LOGGED_OUT -> {
LoginFlow(...)
}
LOGGING_OUT -> {
LoggingOut(onComplete = {
setState(LOGGED_OUT)
})
}
LOGGED_IN -> {
try {
UserFlow(...)
} catch (ex: MyException) {
setState(LOGGING_OUT)
}
}
}
}
Adam Powell
05/17/2020, 12:49 PMUserFlow
that triggers the exception, how and what do we restart about the callers when those callers don't have a stack frame anywhere? They completed running long ago. Control flow isn't in the try block anymore.grandstaish
05/17/2020, 1:24 PMTimo Drick
05/17/2020, 8:00 PM