Skip to content

Instantly share code, notes, and snippets.

@sajjadyousefnia
Created March 13, 2024 19:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sajjadyousefnia/e81fdd540229465060619e8320dbf7aa to your computer and use it in GitHub Desktop.
Save sajjadyousefnia/e81fdd540229465060619e8320dbf7aa to your computer and use it in GitHub Desktop.
class MainViewModel : BaseViewModel<MainContract.Event, MainContract.State, MainContract.Effect>() {
/**
* Create initial State of Views
*/
override fun createInitialState(): MainContract.State {
val currentTime = Calendar.getInstance().getTime()
return MainContract.State("sajjad-agha-gole-bagha + $currentTime")
}
override fun handleEvent(event: MainContract.Event) {
viewModelScope.launch {
setState {
copy(variable = (Calendar.getInstance().getTime().toString()))
}
}
}
}
class MainContract {
// Events that user performed
sealed class Event : UiEvent {
data object OnButtonClicked : Event()
}
// Ui View States
data class State(
val variable: String
) : UiState
// View State that related to Random Number
sealed class GettingValue {
data class ReceiveValue(val value: String) : GettingValue()
}
// Side effects
sealed class Effect : UiEffect {
data object ShowSnack : Effect()
}
}
public abstract class BaseViewModel<Event : UiEvent, State : UiState, Effect : UiEffect> :
ViewModel() {
// Create Initial State of View
private val initialState: State by lazy { createInitialState() }
abstract fun createInitialState(): State
// Get Current State
val currentState: State
get() = uiState.value
private val _uiState: MutableStateFlow<State> = MutableStateFlow(initialState)
val uiState = _uiState.asStateFlow()
private val _event: MutableSharedFlow<Event> = MutableSharedFlow()
val event = _event.asSharedFlow()
private val _effect: Channel<Effect> = Channel()
val effect = _effect.receiveAsFlow()
/**
* Set new Event
*/
protected fun setEvent(event: Event) {
val newEvent = event
viewModelScope.launch { _event.emit(newEvent) }
}
/**
* Set new Ui State
*/
protected fun setState(reduce: State.() -> State) {
val newState = currentState.reduce()
_uiState.value = newState
}
/**
* Set new Effect
*/
protected fun setEffect(builder: () -> Effect) {
val effectValue = builder()
viewModelScope.launch { _effect.send(effectValue) }
}
init {
subscribeEvents()
}
/**
* Start listening to Event
*/
private fun subscribeEvents() {
viewModelScope.launch {
event.collect {
handleEvent(it)
}
}
}
/**
* Handle each event
*/
abstract fun handleEvent(event: Event)
}
interface UiState
interface UiEvent
interface UiEffect
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
// A surface container using the 'background' color from the theme
MaterialTheme {
Surface(
modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background
) {
CallbackCatcher(this)
}
}
}
}
}
private val viewModel = MainViewModel()
@Composable
fun CallbackCatcher(context: Context) {
Column {
Button(modifier = Modifier.requiredSize(200.dp, 150.dp), onClick = {
viewModel.handleEvent(MainContract.Event.OnButtonClicked)
}) {
Text("sajjad agha gole bagha")
}
}
MyTextField()
}
@Composable
fun MyTextField() {
val textState = viewModel.uiState.collectAsState().value.variable
val viewModel = MainViewModel()
Text(
text = textState,
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment