Skip to content

Instantly share code, notes, and snippets.

@sphrak
Last active July 19, 2020 13:08
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 sphrak/51913e5a40db99b70d940a4b5150aee5 to your computer and use it in GitHub Desktop.
Save sphrak/51913e5a40db99b70d940a4b5150aee5 to your computer and use it in GitHub Desktop.
MVI -- Example 1 -- ConflatedBroadcastChannel
class MainActivity : AppCompatActivity(R.layout.activity_main) {
@Inject
lateinit var viewModel: MainActivityViewModel
@Inject
lateinit eventChannel: ConflatedBroadcastChannel<MainActivityView.Event>
private var isInitialised: Boolean = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
init()
}
private fun init() {
if (!isInitialised) {
lifecycleScope.launch {
viewModel()
.flowOn(
Dispatchers.IO
).collect(::render)
}
eventChannel
.offer(
MainActivityView.Event.OnViewInitialised
)
isInitialised = true
}
}
private suspend fun render(state: MainActivityView.State): Unit =
when (state.renderEvent) {
MainActivityView.RenderEvent.Idle -> Unit
is MainActivityView.RenderEvent.DisplayText ->
renderDisplayText(text = state.renderEvent.text)
}
private fun renderDisplayText(text: String) {
// render text
}
}
object MainActivityView {
sealed class Event {
object OnViewInitialised : Event()
data class OnButtonClicked(val idOfItemClicked: Int) : Event()
}
data class State(
val renderEvent: RenderEvent = RenderEvent.Idle
)
sealed class RenderEvent {
object Idle : RenderEvent()
data class DisplayText(val text: String) : RenderEvent()
}
}
class MainActivityViewModel constructor(
private var state: MainActivityView.State = MainActivityView.State(),
private val eventChannel: ConflatedBroadcastChannel<MainActivityView.Event>,
) {
suspend fun invoke(): Flow<MainActivityView.State> =
eventChannel
.asFlow()
.flatMapLatest { event: MainActivityView.Event ->
reduce(event)
}
private fun reduce(event: MainActivityView.Event): Flow<MainActivityView.State> =
when (event) {
MainActivityView.Event.OnViewInitialised -> onViewInitialisedEvent()
MainActivityView.Event.OnButtonClicked -> onButtonClickedEvent(event.idOfItemClicked)
}
private fun onViewInitialisedEvent(): Flow<MainActivityView.State> = flow
val renderEvent = MainActivityView.RenderEvent.DisplayText(text = "hello world")
state = state.copy(renderEvent = renderEvent)
emit(state)
}
private fun onButtonClickedEvent(idOfItemClicked: Int): Flow<MainActivityView.State> = flow
// do something to handle click
println("item clicked: $idOfItemClicked")
emit(state)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment