Looking through the samples I seen 2 approaches to MVVM using Android Architecture Components.
First approach:
ViewModel
provides LiveData
Activity
subscribes to LiveData
Activity
is setting data to ViewModel
ObservableField
. ViewModel
is passed to binding. In xml
you just set ObservableField
as value
<ProgressBar android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" app:visibleGone="@{viewmodel.listLoading}"/> <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/swiperefresh" android:layout_width="match_parent" android:layout_height="match_parent" app:refreshing="@{viewmodel.listRefreshing}" app:onRefreshListener="@{() -> viewmodel.refreshList()}" app:visibleGone="@{!viewmodel.listLoading}">
Pros: I don't need to pass state (for example "loading"), as I update listLoading
ObservableField
in ViewModel
as this:
val listLoading = ObservableBoolean(false)
/** other observable fields go here **/
val list: MutableLiveData<List<Item>> = MutableLiveData()
fun loadList() {
listLoading.set(true)
repo.getList { items ->
list.value = items
listLoading.set(false)
}
}
Cons: Are there any cons in this approach?
Second approach:
ViewModel
provides LiveData
Activity
subscribes to LiveData
Activity
is passed to binding Pros: Any pros of this approach?
Cons: State should be returned from ViewModel
. In this sample from Google data is wrapped in Resource
object.
First approach is used in another sample app from Google
I would like to know what are pros and cons of both patterns from developers with more experience working with Android Data Binding and Android Arch Components.
You should consider splitting view-logic with business-logic.
Since you have a ViewModel using databinding and AAC to handle that you should also seperate the logic inside your view (layout).
Just pass two variables to your layout. One is the VievModel which handle business-logic like pressing a button and processing the logic, the second one is the View (fragment).
After that you can use
app:onRefreshListener="@{() -> yourViewFragment.refreshList()}"
and avoid having "context leaks" or a not working solution if there's currently no view subscribed.
Since the onRefreshListener is bound to a fragment its OK to pass that inside your fragment.
You shoudnt create a LiveData or ObservableField inside your ViewModel to handle that kind of operations because if you pause and resume the fragment you'r going to observe the LiveData again. That also means that you will get the last data delivered again.
Example which can be used in the ViewModel:
<Textview ... name="@{viewModel.dataOfYourModel}" onClick="@{viewModel.doNetworkCall}" />
Golden rule: Every package/import beginning with android.* should be NOT inside the viewmodel except the android.arch.* components.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.