Step #3: Reacting to the Loaded Status

Right now, we have the loading widget set as VISIBLE and the empty widget set as GONE. We already have code to display the empty widget when that is appropriate. We need to add in some smarts to hide the loading widget at the same time.

So, change the observer in the onViewCreated() function of RosterListFragment to be:

    viewLifecycleOwner.lifecycleScope.launchWhenStarted {
      motor.states.collect { state ->
        adapter.submitList(state.items)

        binding?.apply {
          loading.visibility = if (state.isLoaded) View.GONE else View.VISIBLE

          when {
            state.items.isEmpty() && state.isLoaded -> {
              empty.visibility = View.VISIBLE
              empty.setText(R.string.msg_empty)
            }
            else -> empty.visibility = View.GONE
          }
        }
      }
    }

Then, remove this line from onViewCreated():

    binding?.empty?.visibility = View.GONE

If you run the app, you will not see any differences, most likely. Loading a few to-do items — if any — from the database will be fairly quick. And, we have no good way to tell Room to pretend to be slow.

If you would like to see the ProgressBar, you could delay the response from ToDoRepository to the items() call, such as:

  fun items(): Flow<List<ToDoModel>> =
    store.all().map { all -> all.map { it.toModel() } }
      .onStart { delay(5000) }

onStart() tells the Flow to do some work when we start observing the flow. Here, we introduce a five-second delay, using delay(5000).

If you make that change, then run the app, you will see the ProgressBar for five seconds, after which it vanishes and is replaced by the items list or the empty state. After seeing the effect, remove the .onStart { delay(5000) }, so you do not have to wait the extra time in the remaining tutorials.


Prev Table of Contents Next

This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.