Hi! Can I ask a quastion?  How I can correctly dis...
# mvikotlin
e
Hi! Can I ask a quastion?  How I can correctly display a dialog using Label without using a State? For instance. I check some condition in Executor in SimpleBootstrapper and according to result of the condition I decide to show user some dialog.
a
Hi! Are you asking how to emit labels from executor or how to receive labels in a view?
e
second one) How to receive it in view
without using state. Just some dialogs, toasts and so on
a
Well, probably I need to describe this in the documentation. For now you can take the following general advice and adjust it for your needs. Define methods in view:
Copy code
interface TodoListView : MviView<Model, Event> {
    fun showError(text: String)
    // Omitted code
}
Bind labels to view:
Copy code
override fun onViewCreated(todoListView: TodoListView, viewLifecycle: Lifecycle) {
        bind(viewLifecycle, BinderLifecycleMode.START_STOP) {
            todoListStore.labels bindTo { todoListView.handleLabel(it) }
        }
    }

    private fun TodoListView.handleLabel(label: TodoListStore.Label): Unit =
        when (label) {
            is TodoListStore.Label.LoadingError -> showError(text = "Loading failed")
        }
Also you may prefer a separate sealed class in the view: Action. In this case you can write a mapper from Label to Action. Then you will just handle all Actions in the view. Both examples are exhaustive, so if you add one more Label the code won't compile unless you cover the new case.
e
very detailed, thank you. But how do right if I have separate class TodoListBinder? I need to pass context of my “TodoListFragment” into the onViewCreated() and next in handleLabel() ? Like this (In separate TodoListBinder):
Copy code
fun onViewCreated(todoListView: TodoListView, todoListfragment: TodoListFragment) {
        bind(viewLifecycle, BinderLifecycleMode.START_STOP) {
            todoListStore.labels bindTo { todoListView.handleLabel(it, todoListfragment) }
        }
}

private fun handleLabel(label: TodoListStore.Label, fragment: TodoListFragment) {
    when (label) {
        is TodoListStore.Label.LoadingError -> fragment.showDialog()
    }
In Fragment:
Copy code
fun showDialog() {
	// some dialog?
}
a
Yes, you will need to pass the
Context
into
onViewCreated
.
Copy code
private class ViewLabelHandler(
    private val view: TodoListView,
    private val context: Context
) : (TodoListStore.Label) -> Unit {
    override fun invoke(label: TodoListStore.Label) =
        when (label) {
            is TodoListStore.Label.LoadingError -> view.showError(text = context.getString(R.string.error_msg))
        }
}
Copy code
override fun onViewCreated(todoListView: TodoListView, viewLifecycle: Lifecycle, context: Context) {
        bind(viewLifecycle, BinderLifecycleMode.START_STOP) {
            todoListStore.labels bindTo ViewLabelHandler(todoListView, context)
        }
    }
You may also want to improve unit testing by abstracting the
Context
with an interface:
Copy code
interface Resources {
    val errorMsg: String
}
e
thx a lot!) 🙏
👍 1