tl;dr
Library | Description |
---|---|
binding-collection-adapter | Bind RecyclerView, ListView, ViewPager and Spinner |
bindable-radiobuttons | Bind RadioButton, ToggleButton, Checkbox and lists of Buttons |
useful BindingAdapter | Reduce boilerplate further and the need for common support properties |
Introduction
The Android Databinding library is tried and tested tool for enabling MVVM architecture in your Android apps. It helps you move code from your activities, fragments and views to your ViewModel. From the outset the library lacked what I belive to be some core features, like binding to RecyclerView and groups of RadioButtons. In this article I will present a couple of libraries that fill these gaps and more.With these simple add-ons I believe DataBinding is a highly effective and fun way of coding solid unit-testable MVVM apps on Android.
List- And RecyclerViews
Evan Tatarka's Binding-Collection-Adapter library solves binding to RecyclerViews elegantly. You have one XML view for the individual items and a ViewModel class that represents them. If you have multiple view types for the list you can override the binding code.This solution rids of the adapter. Less code. Better architecture. It also suppoerts ListView, Spinner and ViewPager
Example
Below is a minimal example to lay out the concept. A RecyclerView with two bound, each item has the text and the color property bindable. Read the official documentation for a complete, compilable example.Result:
Main view:
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:items="@{viewModel.items}"
app:itemBinding="@{viewModel.itemBinding}"/>
Item view:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="itemVM" type="com.nilsenlabs.bindingblog.ItemVM" />
</data>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@{itemVM.text}"
android:textColor="@{itemVM.color}">
</TextView>
</layout>
Main ViewModel
class MainVM {
val items: ObservableList = ObservableArrayList()
val itemBinding: ItemBinding = ItemBinding.of(BR.itemVM, R.layout.item)
init {
items.add(ItemVM("One", Color.BLACK))
items.add(ItemVM("Two", Color.GREEN))
}
}
Item ViewModel
class ItemVM(
val text: String,
val color: Int
)
RadioButtons, CheckBoxes and list of Buttons
This one I built myself: I needed to bind a list of RadioButtons to data fetched from a remote service. The number of RadioButtons will vary. A common use case (with or without the service), but not supported out of the box from Google's Data Binding library. My library, bindable-radiobuttons, also support check boxes, toggle buttons and regular buttons. To produce the screenshot below implement the following:
View:
<com.nilsenlabs.bindableradiobuttons.radiobuttons.BindableRadioButtonList
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:itemViewId="@layout/my_radio"
app:selectedItem="@={viewModel.selectedRadioButton}"
app:buttons="@{viewModel.radioButtons}"
/>
ViewModel
val radioButtons = listOf(
RadioButtonViewModel("One"),
RadioButtonViewModel("Two", isEnabled = false),
RadioButtonViewModel("Three")
)
val selectedRadioButton = ObservableField<RadioButtonViewModelInterface>(radioButtons[2])
Useful Binding Adapters
You need a handful of extra binding adapters on top of what Google provides to solve a set of common use cases.Gist with BindingAdapters on Github here
Name | Input type | Binds to | Function |
---|---|---|---|
app:visibleOrGone | Boolean | Visiblity | true means Visible, false means Gone. My number 1 most used binding adapter. |
app:visibleOrInvisible | Boolean | Visiblity | true means Visible, false means Invisible |
app:goneIfNull | Any | Visiblity | null means Gone, non-null means Visible. Perfect if you want a text view to be gone when the String is null. |
app:onClick | None | clickListener | Just a click listener that doesn't send "view: View" as unnecessary input parameter |
android:src | Int | src | Allows you to bind a drawable resources as Int to an ImageView. Google only allows Drawable objects out of the box, which will force you to depend on a Resource object in the VM |
android:text | Int | text | An improvement to standard TextView text binding that doesn't crash when the value 0 is bound. |
No comments:
Post a Comment