For the More Curious: More About Data Binding

Complete coverage of data binding is outside the scope of this book. And yet, reader, we must nevertheless try.

Lambda expressions

You can write short callbacks directly in your layout file by using lambda expressions. These are simplified versions of Java’s lambda expressions:

    <Button
        android:layout_width="match_parent"
        android:layout_height="120dp"
        android:text="@{viewModel.title}"
        android:onClick="@{(view) -> viewModel.onButtonClick()}"
        tools:text="Sound name"/>

Like Java 8 lambda expressions, these are turned into implementations for the interface you use them for. (In this case, View.OnClickListener.) Unlike Java 8 lambda expressions, these expressions must use this exact syntax: The parameter must be in parentheses, and you must have exactly one expression on the right-hand side.

Also, unlike in Java lambdas, you can omit the lambda parameters if you are not using them. So this works fine, too:

    android:onClick="@{() -> viewModel.onButtonClick()}"

Syntactic sugar

You also get a few additional bits of handy syntax for data binding. Particularly handy is the ability to use backticks for double quotes:

    android:text="@{`File name: ` + viewModel.title}"

Here, `File name` means the same thing as "File name".

Binding expressions also have a null coalescing operator:

    android:text="@{`File name: ` + viewModel.title ?? `No file`}"

In the event that title is null, the ?? operator will yield the value "No file" instead.

In addition, automatic null handling is provided for you in data binding expressions. Even if viewModel is null in the code above, data binding will provide appropriate null checks so that it does not crash the app. Instead of crashing, the subexpression viewModel.title will yield "null".

BindingAdapters

By default, data binding interprets a binding expression as a property invocation. So this:

    android:text="@{`File name: ` + viewModel.title ?? `No file`}"

Is translated into an invocation of the setText(String) function.

Sometimes that is not enough, and you want some custom behavior to be applied for a particular attribute. In those cases, you can write a BindingAdapter:

    @BindingAdapter("app:soundName")
    fun bindAssetSound(button: Button, assetFileName: String ) {
        ...
    }

Simply create a file-level function anywhere in your project and annotate it with @BindingAdapter, passing in the name of the attribute you want to bind as a parameter to the annotation and the View to which the annotation applies as the first parameter to the function. (Yes, this really works.)

In the example above, whenever data binding encounters a Button with an app:soundName attribute containing a binding expression, it will call your function, passing the Button and the result of the binding expression.

You can even create BindingAdapters for more generalized views, such as View or ViewGroup. In this case the BindingAdapter will apply to that View and all of its subclasses.

For example, if you wanted to define an attribute app:isGone that would set the visibility of any View based on a Boolean value, you could do that like so:

    @BindingAdapter("app:isGone")
    fun bindIsGone(view: View, isGone: Boolean ) {
        view.visibility = if (isGone) View.GONE else View.VISIBLE
    }

Because View is the first argument to bindIsGone, this attribute is available to View and all subclasses of View in your app module. This means you can use it with Buttons, TextViews, LinearLayouts, and so on.

You will probably think of one or two operations you would like to use data binding with on the standard library widgets. Many common operations already have binding adapters defined – for example, TextViewBindingAdapter provides additional attributes for TextView. You can read these binding adapters yourself by viewing the source in Android Studio. So, before you write your own solution, type Command-Shift-O (Ctrl-Shift-O) to search for a class, open up the associated binding adapters file, and check to see whether it already exists.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.201.71