Ma2340
Ma2340

Reputation: 727

Android recycler view initially always empty

I have a viewmodel like this -

private val viewState = SchoolsViewState()

    fun onViewOpened() =
        Transformations.map(schoolUseCase.performAction(SchoolAction.GetList)) {
            when (it) {
                is SchoolResult.Loading -> viewState.copy(loading = true)
                is SchoolResult.ListContent -> viewState.copy(loading = false, listData = it.schoolList)
                is SchoolResult.Error -> viewState.copy(loading = false, error = it.error)
                else -> viewState.copy(loading = false)
            }
        }

The viewState class looks like that -

data class SchoolsViewState(
    val loading: Boolean = false,
    val schoolList: List<SchoolModel> = emptyList(),
    val error: SchoolResult.ErrorType? = null
)

The Fragment view model observe code looks like this -

viewModel.onViewOpened().observe(this, Observer {
//Handling the SchoolsViewState here
            swipeContainer.isRefreshing = it.loading

            if (it.schoolList.isNullOrEmpty()) {
                view?.recycler_view?.visibility = View.GONE
                view?.empty_view?.visibility = View.VISIBLE
            } else {
                view?.recycler_view?.visibility = View.VISIBLE
                view?.empty_view?.visibility = View.GONE
                view?.recycler_view?.adapter = schoolAdapter
                myAdapter.setSchoolList(it.schoolList)
            }
        })

The problem is on every swipe refresh I see empty view first and once data is there then i see list of schools. So this is kind of a UI inconvenience. This is due to viewState.copy(...) on every refresh gives new state to the UI. How can I overcome this problem?

Upvotes: 1

Views: 428

Answers (2)

Anatolii
Anatolii

Reputation: 14660

You shouldn't show an empty view if your list is empty because the list is still being loaded - that doesn't make sense. Instead, you should show it only if loading = false and your list is empty. In this case, you really don't have any other option. Hence, you code could look as follows:

viewModel.onViewOpened().observe(this, Observer {
//Handling the SchoolsViewState here
        swipeContainer.isRefreshing = it.loading

        // if means the loading is finished 
        if (!it.loading) {
            if (it.schoolList.isNullOrEmpty()) {
                view?.recycler_view?.visibility = View.GONE
                view?.empty_view?.visibility = View.VISIBLE
            } else {
                view?.recycler_view?.visibility = View.VISIBLE
                view?.empty_view?.visibility = View.GONE
                view?.recycler_view?.adapter = schoolAdapter
                myAdapter.setSchoolList(it.schoolList)
            }
        } else {
            // here you could show some loading progress or similar
        }
    })

Upvotes: 2

donfuxx
donfuxx

Reputation: 11323

You are updating a different adapter's list than the one that is set as your recyler view´s adapter, see bookingsAdapter vs myAdapter:

view?.recycler_view?.adapter = bookingsAdapter
myAdapter.setSchoolList(it.schoolList)

That looks strange to me

Upvotes: 0

Related Questions