-
Notifications
You must be signed in to change notification settings - Fork 8
Part1.2
- 1.0 - Preparing
- 1.1 - First ViewModel & LiveData with Weather Detail View
- 1.2 - ViewModel & Events with the Splash View
- 1.3 - Shared ViewModel between Activity/Fragments, with the Weather 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
.
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.
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.
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()
In package splash
:
-
Create
SplashViewModel
class and make it inherits fromRxViewModel
- 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 fromSplashPresenter
, and use theevents
SingleLiveEvent prooperty withPending
,Success
andError
events instead of View calls (it's the same LiveData API under the hood, reusevalue
orpostValue()
).
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()) }
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 onviewModel.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
toviewModel
Note π: by viewModel()
is the equivalent to ViewModelProviders.of(this).get(...)
but is lazy and provide constructor dependency injection
Check that the app is OK on your device (you can start the app and load default weather).
For unit test:
- Comment
SplashPresenterMockTest
test - Uncomment the
SplashViewModelMockTest
OR write your own SplashViewModelMockTest test - You can safely remove
SplashPresenter
file