[翻译] Android Data Binding(3): 让v

作者: luisxu | 来源:发表于2017-03-14 22:29 被阅读132次

    原文地址: https://medium.com/google-developers/android-data-binding-adding-some-variability-1fe001b3abcc#.xjl7y8ohh

    你是否看过别人的layout并想:这个值在哪里设置和获取.或者,你觉得不需要findViewById了是很好的一个开始,但仍然存在很多样板代码.Android Data Binding让这个变得简单.

    使用ViewHolder模式<a id="orgheadline3"></a>

    假设我们需要在应用中显示用户信息. 在前面,我展示了使用Android Studio
    通过如下的layout文件生成一个"View Holder"类:

    user_info.xml
    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android">
        <LinearLayout
                android:orientation="vertical"
                android:layout_width="match_parent"
                android:layout_height="match_parent">
            <ImageView
                    android:id="@+id/userImage"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"/>
            <TextView
                    android:id="@+id/userFirstName"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"/>
    
            <TextView
                    android:id="@+id/userLastName"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"/>
        </LinearLayout>
    </layout>
    

    然后给View设置数据:

    private void setUser(User user, ViewGroup root) {
        UserInfoBinding binding =
            UserInfoBinding.inflate(getLayoutInflater(), root, true);
        binding.userFirstName.setText(user.firstName);
        binding.userLastName.setText(user.lastName);
        binding.userImage.setImageBitmap(user.image);
    }
    

    虽然这看上去要比findViewById好, 但仍然存在很多的样板代码!
    可以通过在layout文件中使用data binding表达式来消除这些样板代码,
    实现自动赋值.

    给变量赋值<a id="orgheadline4"></a>

    首先, 增加一个binding表达式需要的 data 标签以及一个相关变量.
    然后, 对于layout中需要赋值的属性, 使用binding表达式.

    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android">
        <data>
            <variable
                name="user"
                type="com.example.myapp.model.User"/>
        </data>
        <LinearLayout
                android:orientation="vertical"
                android:layout_width="match_parent"
                android:layout_height="match_parent">
            <ImageView
                    android:src="@{user.image}"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"/>
            <TextView
                    android:text="@{user.firstName}"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"/>
    
            <TextView
                    android:text="@{user.lastName}"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"/>
        </LinearLayout>
    </layout>
    

    标签中的binding表达式表示为 "@{…}" 格式.上述表达式直接将用户的image,firstName,lastName赋值给view的source和text.这样就不用再写样板代码了.但是仍然不知道需要使用那个用户所以需要做分配:

    private void setUser(User user, ViewGroup root) {
        UserInfoBinding binding =
            UserInfoBinding.inflate(getLayoutInflater(), root, true);
        binding.setUser(user);
    }
    

    很简单!

    从上述layout文件可以看到,View没有ID. 那我们在前面文章中试图生成的View Holder呢? 因为数据直接被绑定到了view上, 所以这里就不需要再去访问view了! 只是简单的设置变量,所有事情就完成了.

    而且犯错的几率也变小了.例如, 你在横屏模式下没有用户图片,那么就不需要检查ImageView是否存在. 每个layout都会计算binding表达式, 如果没有ImageView,就不会执行更新代码.

    这并不意味着View Holder就过时了. 还有很多时候你会需要直接访问view.只是这种情况比以前少了很多.

    Include Layouts<a id="orgheadline5"></a>

    那么, 包含的layout怎么办? 同样可以使用该功能, 就想View Holder模式一样.例如, 假设展示用户名称的TextView在一个被包含的layout中:

    user_name.xml
    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android">
        <data>
            <variable
                    name="user"
                    type="com.example.myapp.model.User"/>
        </data>
    
        <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="horizontal">
            <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="@{user.firstName}"/>
    
            <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="@{user.lastName}"/>
        </LinearLayout>
    </layout>
    

    可以在外层的layout中用如下方式来赋值user变量:

    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto">
        <data>
            <variable
                    name="user"
                    type="com.example.myapp.model.User"/>
        </data>
        <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical">
            <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:src="@{user.image}"/>
            <include
                    layout="@layout/user_name"
                    app:user="@{user}"/>
        </LinearLayout>
    </layout>
    

    当user被设置时(通过代码 binding.setUser(…)), 被包含的layout的user变量也会被设置,因为设置了 *app:user="@{user}"*. 再次注意, 因为被包含的layout的view不需要被直接访问,(我甚至都没有设置id), 这里没有给include设置ID.

    相关文章

      网友评论

        本文标题:[翻译] Android Data Binding(3): 让v

        本文链接:https://www.haomeiwen.com/subject/lrjknttx.html