What should a viewState class look like in mvi architecture android?

Viewed 278

In MVI architecture for Android there is a class called uiState. In the demos that I found on medium, github and youtube, this class is either a simple sealed class, or a data class that contains a variable or idle classes, loads, success with the necessary data and an error.

sealed class MainNewsState {
    object Idle : MainNewsState()
    object Loading : MainNewsState()
    data class Error(val string: String) : MainNewsState()
    data class Success(val listNews: List<ArticleDb>) : MainNewsState()
}

But if you need to show two data types in a fragment, you want to display not at the same time, where the second data type is the result of the first. For example, in my task, I first get the news topics previously selected by the user, from sharedpreferences, then I must draw the name of the news topics and then I must receive news on this topic and draw them accordingly.

In my task, the uiState contains two successful results. And the question is how this class should look like?

I thought about it and decided that there are two options for solving this gaps. First, create a sealed class that contains the state of the news topics and received news. But then the problem arises that my uiState does not describe the complete picture of the user interface. And it seems to me that this is not quite the right decision.

sealed class MainNewsState {
        object Idle : MainNewsState()
        data class Loading(val listNews: List<ArticleDb>?) : MainNewsState()
        data class Error(val string: String) : MainNewsState()
        data class newsTopicsSuccess(val listTopicNews: List<String>) : MainNewsState()
        data class newsSuccess(val listNews: List<ArticleDb>) : MainNewsState()
    }

Another option is to use a date class in which variables for news topics and the news themselves will be stored.

data class MainNewsState(
        val isIdle: Boolean = false,
        val isLoading: Boolean = false,
        val newsTopicsSuccess: List<String>? = null,
        val newsSuccess: List<News>? = null, 
        val error: String? = null
    )

And when processing states in a fragment, I can get the desired result, but in a situation where I first get news topics, draw them on the screen, then receive news and when processing them, I will re-draw news topics, and then the news itself.

viewModel.uiState.collect {
            if (it.isLoading) {
                showLoading()
            }
            it.error?.let {
                showError(it)
            }
            it.newsTopicsSuccess?.let {
                renderNewsTopics(it)
            }
            it.newsSuccess?.let {
                renderNews(it)
            }
        }

Of course, I can add some flag that will display whether I have drawn news topics, but it seems that this is also not the best architectural solution.

0 Answers
Related