-
Notifications
You must be signed in to change notification settings - Fork 8
Part1.1
- 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
This view simply displays weather detail chosen from weather view. Let's start our new ViewModel class from the DetailPresenter
class (package view/detail
).
Create the DetailViewModel
class from the DetailPresenter
class. Write the getDetail()
function to push states with LiveData
(as Loading
,DetailLoaded
and Failed
states). Update the DetailActivity
to use the ViewModel instead of Presenter.
Let's create our ViewModel class:
- Create class
DetailViewModel
indetail
package and make it inherits fromRxViewModel
We won't use any constructor injection for now, as the default ViewModel API doesn't allow us to do so (In next exercises, we will use Koin).
- Write the following properties:
class DetailViewModel : RxViewModel() {
/*
* Dependencies out of constructor. Will be filled later by DetailActivity
*/
lateinit var dailyForecastRepository: DailyForecastRepository
lateinit var schedulerProvider: SchedulerProvider
- Write a data class to represent our view state, at the end of
DetailViewModel
class:
data class DetailLoaded(val weather: DailyForecast) : ViewModelState()
- Add LiveData property called states (backed by private
MutableLiveData
):
private val _states = MutableLiveData<ViewModelState>()
val states: LiveData<ViewModelState>
get() = _states
-
Copy the
getDetail()
function fromDetailPresenter
and use thestates
property to writeDetail
,Loading
andFailed
instead of calling MVP View.
_states.value = Loading
_states.value = DetailLoaded(...)
_states.value = Failed(...)
Warning value
or postValue
. This last is used when app is in background.
Android Architecture ViewModel API is used here without any dependency injection support for this exercise.
In app_module.kt
, just delete the presenter declaration from Koin:
// Delete this
factory<DetailContract.Presenter> { DetailPresenter(get(), get()) }
We need to declare our ViewModel in DetailActivity.kt
in order to use the getDetail()
function and listen to ViewModel states.
- Remove overrides from
DetailContract
- Remove
onStart()
,onStop()
functions andpresenter
property
Now prepare your DetailViewModel:
- In
onCreate()
function, declare theDetailViewModel
ViewModel withViewModelProviders
:
val detailViewModel = ViewModelProviders.of(this).get(DetailViewModel::class.java)
- Then get dependencies for
DetailViewModel
with Koin:
// Apply dependencies "manually"
detailViewModel.apply {
// import org.koin.android.ext.android.get to use the get() function, to retrieve dependencies from an Activity
dailyForecastRepository = get()
schedulerProvider = get()
}
- And now let's observe our
detailViewModel
for incoming states. We use the KotlinWhen
pattern matching to bindFailed
andDetail
:
detailViewModel.states.observe(this, Observer { state ->
when (state) {
is Failed -> showError(state.error)
is DetailViewModel.DetailLoaded -> showDetail(state.weather)
}
})
- Finally, call the
getDetail()
function fromdetailViewModel
, withdetailId
property
Warning
Check that the app is OK on your device (you can select a weather detail).
For unit test:
- Comment
DetailPresenterMockTest
test - Uncomment the
DetailViewModelMockTest
OR write your own DetailViewModelMockTest test - You can safely delete
DetailPresenter
class.