Skip to content

Part1.2

Arnaud Giuliani edited this page Mar 5, 2019 · 35 revisions

Steps



1.2 - ViewModel & Events with the Splash View

The splash view is displayed only once at app start, to preload the weather to display. Let's go with the SplashPresenter class from package view/splash.

Why do we need events?

We want to reload data during our splash screen, every time we start it. Thus, we can't use LiveData as it will retain the last state of our view. That's why we need a more transient way of pushing data with LiveData. An event is a represented by a particular LiveData type: SingleLiveEvent. It's a type of stream that doesn't retain the last state.

TL;DR πŸš€

Convert the SplashPresenter into SplashViewModel. Update the getLastWeather() function to push events with SingleLiveEvent (Proceed, Success and Error events). Update the SplashActivity to use the ViewModel instead of Presenter.


TODO 🎯 - Prepare Events

In package view, we prepare some generics events for later use. Write the following Events.kt file:

/**
 * Abstract Event from ViewModel
 */
open class ViewModelEvent

/**
 * Generic Pending Event
 */
object Pending : ViewModelEvent()

/**
 * Generic Success Event
 */
object Success : ViewModelEvent()

/**
 * Generic Error Event
 */
data class Error(val error: Throwable) : ViewModelEvent()

TODO 🎯 - SplashViewModel

In package splash:

  • Create SplashViewModel class and make it inherits from RxViewModel
  • Use the following dependencies in constructor, as we will use Koin to inject it for us.
class SplashViewModel(
   private val dailyForecastRepository: DailyForecastRepository,
   private val schedulerProvider: SchedulerProvider
) : RxViewModel() {
  • Write the events LiveData property backed by SingleLiveEvent:
private val _events = SingleLiveEvent<ViewModelEvent>()
val events: LiveData<ViewModelEvent>
     get() = _events
  • Copy the getLastWeather() function from SplashPresenter, and use the events SingleLiveEvent prooperty with Pending, Success and Error events instead of View calls (it's the same LiveData API under the hood, reuse value or postValue()).

TODO 🎯 - Update Koin configuration

In app_module.kt, replace the Presenter configuration with ViewModel one:

From

// Replace SplashPresenter declaration
factory<SplashContract.Presenter> { SplashPresenter(get(), get()) }

to

// declare SplashViewModel for Splash View
viewModel { SplashViewModel(get(), get()) }

TODO 🎯 - SplashActivity

Let's setup our ViewModel in the SplashActivity to call getLastWeather() and listen for incoming events.

  • Remove onStart(), onStop() functions and overrides from Contract

Let's replace the presenter property by our ViewModel. Let's do it with Koin:

  • declare SplashViewModel with Koin:
private val viewModel : SplashViewModel by viewModel()
  • In onCreate() function, listen for incoming events on viewModel.events. Bind the 3 used events from the ViewModel as follow:
is Pending -> showIsLoading()
is Success -> showIsLoaded()
is Error -> showError(...)
  • And don't forget to call the viewModel.getLastWeather() function to start loading weather data
  • Fix any use of presenter to viewModel

Note πŸ“–: by viewModel() is the equivalent to ViewModelProviders.of(this).get(...) but is lazy and provide constructor dependency injection


Test & Run it πŸ‘

Check that the app is OK on your device (you can start the app and load default weather).

For unit test:


Clone this wiki locally