Skip to content

Instantly share code, notes, and snippets.

@tim4dev
Created July 10, 2024 04:51
Show Gist options
  • Save tim4dev/f8d291f0c76194886ea6ee9375353cff to your computer and use it in GitHub Desktop.
Save tim4dev/f8d291f0c76194886ea6ee9375353cff to your computer and use it in GitHub Desktop.
UiState with arguments
/*
* Copyright (c) 2024 Yuriy Timofeev <[email protected]>
*
* Distributed under the Apache License 2.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*/
/**
* Inspired by https://stackoverflow.com/a/63824909/345810
*/
sealed class UiState<out A, out T> where A : Any?, T : Any? {
object Empty : UiState<Nothing, Nothing>()
data class Arguments<A>(val arg: A?) : UiState<A, Nothing>()
data class Success<A, T>(val arg: A?, val data: T) : UiState<A, T>()
data class Error(val message: String, val error: Throwable) : UiState<Nothing, Nothing>()
fun fold(
onEmpty: () -> Unit,
onArguments: (A?) -> Unit,
onSuccess: (A?, T) -> Unit,
onError: (Error) -> Unit
) {
when (this) {
Empty -> onEmpty.invoke()
is Arguments -> onArguments.invoke(arg)
is Success -> onSuccess.invoke(arg, data)
is Error -> onError.invoke(this)
}
}
}
infix fun <A, T> UiState<A, T>.takeIfSuccess(onSuccess: (A?, T) -> Unit): UiState<A, T> {
return when (this) {
is UiState.Success -> {
onSuccess(arg, data)
this
}
else -> {
this
}
}
}
infix fun <A, T> UiState<A, T>.takeIfArguments(onArguments: (A?) -> Unit): UiState<A, T> {
return when (this) {
is UiState.Arguments -> {
onArguments(arg)
this
}
else -> {
this
}
}
}
// ---------------------------------------------------------------------------------------------------
class StateTest {
private data class MyArguments(
val isVisible: Boolean,
val title: String
)
private data class MyStateData(
val id: Int,
val text: String
)
private var _state: UiState<MyArguments, MyStateData> = UiState.Empty
private val state: UiState<MyArguments, MyStateData>
get() = _state
@Test
fun stateTest() {
// passing arguments
_state = UiState.Arguments(
arg = MyArguments(
isVisible = false,
title = "title 1"
)
)
checkState(state)
// loading data
state.takeIfArguments {
_state = UiState.Success(
arg = it,
data = MyStateData(
id = 1,
text = "text 1"
)
)
}
checkState(state)
// error
_state = UiState.Error(
message = "error message",
error = IOException()
)
checkState(state)
/*
check == onArguments(MyArguments(isVisible=false, title=title 1)
check == onSuccess(MyArguments(isVisible=false, title=title 1), MyStateData(id=1, text=text 1))
check == onError(Error(message=error message, error=java.io.IOException))
*/
}
private fun checkState(uiState: UiState<MyArguments, MyStateData>) {
uiState.fold(
onEmpty = {
println("check == Empty")
},
onArguments = {
println("check == onArguments($it")
},
onSuccess = { arg: MyArguments?, state: MyStateData ->
println("check == onSuccess($arg, $state)")
},
onError = {
println("check == onError($it)")
}
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment