Created
July 10, 2024 04:51
-
-
Save tim4dev/f8d291f0c76194886ea6ee9375353cff to your computer and use it in GitHub Desktop.
UiState with arguments
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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