Android Data Binding 进阶

来源:互联网 发布:linux多开terminator 编辑:程序博客网 时间:2024/06/06 18:51

Android Data Binding 初探
Android Data Binding 进阶
Android Data Binding 配合BaseAdapter

学完 Data Binding 的基本使用方法后,我们来学学 Data Binding 的进阶。

Data Binding 最大的作用就是减少我们在 Activity 写更新和设置 UI 代码,有时候,View的更新过程需要一些简单的逻辑,如判断空,拼接字段等,因此,Android 的 Data Binding 还提供了一些简单的表达式供我们在 xml 布局文件中使用。

例子:

数据类

public class Person extends BaseObservable {    private String name;    private int age;    public Person(String name, int age) {        this.name = name;        this.age = age;    }    @Bindable    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;        notifyPropertyChanged(BR.name);    }    @Bindable    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;        notifyPropertyChanged(BR.age);    }}

xml 布局文件

<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android">    <data>        <variable            name="person"            type="com.johan.study.Person" />    </data>    <LinearLayout xmlns:tools="http://schemas.android.com/tools"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:orientation="vertical"        android:padding="10dp"        tools:context="com.johan.study.MainActivity">        <TextView            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:padding="10dp"            android:textSize="16dp"            android:textColor="@android:color/holo_blue_light"            android:text="@{person.name}"            />    </LinearLayout></layout>

Activity

public class MainActivity extends AppCompatActivity {    private Person person = new Person(null, 25);    private ActivityMainBinding binding;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        binding = DataBindingUtil.setContentView(this, R.layout.activity_main);        binding.setPerson(person);    }}

如果看不懂,请看我博客 Android Data Binding 初探

三元表达式

更新 UI 最常用的逻辑应该是三元表达式了。我们来看看在 xml 布局文件中,三元表达式怎么使用:

<TextView    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:padding="10dp"    android:textSize="16dp"    android:textColor="@android:color/holo_blue_light"    android:text="@{person.name != null ? person.name : @string/app_name}"    />

所有表达式都要写在“@{}”里面:

@{person.name != null ? person.name : @string/app_name}

是不是和我们在 Java 代码写的一样呢?毫无违和感,爽!!

另外,在“@{}”内使用资源,也是和普通的一样,只不过没有提示(这点真的不太好,容易写错)。

三元表达式我们还能这么用:

<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android">    <data>        <!-- import 标签的作用是引入类,和 java 代码一样 -->        <!-- 因为在@{}中使用了View类,我们必须将包引入 -->        <import type="android.view.View" />        <variable            name="person"            type="com.johan.study.Person" />    </data>    <LinearLayout xmlns:tools="http://schemas.android.com/tools"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:orientation="vertical"        android:padding="10dp"        tools:context="com.johan.study.MainActivity">        <!-- visibility 属性使用了三元表达式,如果person的name为null,就设置为View.GONE,和 java 代码一样 -->        <!-- 由于使用了 View 类,需要在data标签引入 View 类 -->        <TextView            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:padding="10dp"            android:textSize="16dp"            android:textColor="@android:color/holo_blue_light"            android:text="@{person.name != null ? person.name : @string/app_name}"            android:visibility="@{person.name != null ? View.VISIBLE : View.GONE}"            />    </LinearLayout></layout>

上面的例子中,如果没有 import View 类的话,编译器是没有提示,你就应该想到要 import 了。

空运算符

Data Binding 还提供一个空运算符“??”

<TextView    android:id="@+id/name_view"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:padding="10dp"    android:textSize="16dp"    android:textColor="@android:color/holo_blue_light"    android:text="@{person.name ?? @string/app_name}"    />

其实

@{person.name ?? @string/app_name}

就等同于

@{person.name != null ? person.name : @string/app_name}

拼接

我们可以在“@{}”内拼接字符

<TextView    android:id="@+id/name_view"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:padding="10dp"    android:textSize="16dp"    android:textColor="@android:color/holo_blue_light"    android:text="@{@string/app_name + person.name}"    />

这样就可以拼接字符了:

@{@string/app_name + person.name}

我们还能拼接“dimen”,在 dimens 资源文件定义的两个距离

<?xml version="1.0" encoding="utf-8"?><resources>    <dimen name="space_1">15dp</dimen>    <dimen name="space_2">8dp</dimen></resources>

拼接 dimen 方式

<TextView    android:id="@+id/name_view"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:padding="@{@dimen/space_1 + @dimen/space_2}"    android:textSize="16dp"    android:textColor="@android:color/holo_blue_light"    android:text="@{person.name}"    />

我们看

@{@dimen/space_1 + @dimen/space_2}

这方便我们计算好距离,然后再设置,不用重新定义新距离,这个功能很有用的。

使用方法

我们在 xml 中不仅可以使用类实例的方法,还能直接使用类的静态方法,就好像 java 一样。

类实例方法就是我们设置的监听事件。

我们来看看怎么使用类的静态方法:

定义静态方法:

public class Utils {    public static String formatName(String name) {        return "姓名:" + name;    }}

xml 布局文件:

<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android">    <data>        <!-- import 标签的作用是引入类,和 java 代码一样 -->        <!-- 因为在@{}中使用了Util类,我们必须将包引入 -->        <import type="com.johan.study.Utils" />        <variable            name="person"            type="com.johan.study.Person" />    </data>    <LinearLayout xmlns:tools="http://schemas.android.com/tools"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:orientation="vertical"        android:padding="10dp"        tools:context="com.johan.study.MainActivity">        <!-- 使用 Utils.formatName 方法 -->        <!-- 由于使用了 Utils类,需要在data标签引入 Utils 类 -->        <TextView            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:padding="10dp"            android:textSize="16dp"            android:textColor="@android:color/holo_blue_light"            android:text="@{Utils.formatName(person.name)}"            />    </LinearLayout></layout>

其实和我们使用 java 代码很相似,很多东西我们不妨用 java 代码试试!

使用数组和集合

在 xml 布局中,我们能定义一个数组,List,Map,通过访问下标,设置属性值。

网上查的我都试了,不知道为什么 Android Studio 不支持定义数组和具体List,暂时还没想到会用到这个,先放着吧!!(知道的,麻烦留言告知,谢谢! ^_^)

其他表达式

数学 + - / * %字符串连接 +逻辑 && ||二进制 & | ^一元运算 + - ! ~移位 >> >>> <<比较 == > < >= <=instanceof分组 ()nullCast方法调用数据访问 []三元运算 ?:

其他表达式自己慢慢探索,你可以的!! just try!!

include

这里再补充一个,我们布局的时候,可能会用到“include”标签来复用布局。如果“include”的 layout 也是一个 Data Binding 的布局文件,里面还绑定了数据,那我们怎么赋值给“include”的 layout 的变量呢?

还是一个例子说明

layout_include.xml

<?xml version="1.0" encoding="utf-8"?><layout  xmlns:android="http://schemas.android.com/apk/res/android">    <data>        <variable            name="person"            type="com.johan.study.Person" />    </data>    <LinearLayout        android:orientation="vertical"        android:layout_width="wrap_content"        android:layout_height="wrap_content">        <TextView            android:id="@+id/name_view"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:padding="10dp"            android:textSize="16dp"            android:textColor="@android:color/holo_blue_light"            android:text="@{person.name}"            />    </LinearLayout></layout>

“include”的文件里面定义了person变量。

activity_main.xml 布局文件

<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:binding="http://schemas.android.com/apk/res-auto">    <data>        <variable            name="person"            type="com.johan.study.Person" />        <variable            name="handler"            type="com.johan.study.MainActivity.NameHandler" />    </data>    <LinearLayout xmlns:tools="http://schemas.android.com/tools"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:orientation="vertical"        android:padding="10dp"        tools:context="com.johan.study.MainActivity">        <EditText            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:padding="10dp"            android:hint="输入姓名"            android:inputType="text"            android:textSize="16dp"            android:onTextChanged="@{handler.onTextChanged}"            />        <!-- 在 xml 文件直接传值给 include 的 layout 中 -->        <include            layout="@layout/layout_include"            binding:person="@{person}"            />    </LinearLayout></layout>

我们通过 xml 文件可以直接把值赋给“include”layout 的 person 变量中,挺方便的!!