zoukankan      html  css  js  c++  java
  • Android数据绑定DataBinding(一)入门篇

    早上看到了一篇推文“还在使用繁琐的findViewById,跟着尝试了一下DataBinding,之前使用ButteKnife就已经干掉了findViewById。因为写过微信小程序,那种在js中数据源改变,UI中的数据跟着改变,真的很爽。

    本文个人拙见,如果有误人子弟处,请提出,感激——来自小渣渣的颤抖

    配置

    关于DataBinding的介绍不说了,我也没搞懂,先会用。
    appbuild.gradle中添加如下内容,表示支持数据绑定,(个人理解)因为使用数据绑定会通过布局文件自动生成许多的东西,见后面。

    android {
    	.....
        dataBinding {
            enabled = true;
        }
    }
    

    布局使用

    新建一个activity,在其layout中使用如下

    <layout>
        <data>
            <variable name="user" type="com.jiajia.mypractisedemos.module.jetpack.User"/>
        </data>
    
        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            tools:context="com.jiajia.mypractisedemos.module.jetpack.JetpackActivity">
    
            <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.userName}"/>
    
            <Button
                android:layout_width="wrap_content"
                android:text="更换User"
                android:layout_height="wrap_content" />
    	......
        </LinearLayout>
    </layout>
    

    这里布局的根节点不是平时使用的几大布局了,而是layout,看其他的文章说使用layout会自动生成绑定类(见后面)。
    在data标签下新建变量variable,设置name属性和type属性,name随便取,在本xml中使用,这里的type可以是我们平时使用的基本数据类型,也可以是自己封装的类等,显而易见就是布局文件需要使用的数据,这里定义了一个User类,多么通用的栗子啊。User类就是个简单的Model啦

    public class User{
        private String userName;
        private int age;
    
        public User(String userName, int age) {
            this.userName = userName;
            this.age = age;
        }
        public String getUserName() {
            return userName == null ? "" : userName;
        }
    
        public void setUserName(String userName) {
            this.userName = userName;
        }
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    

    再回到xml中,这里复制一下TextView节点,便于浏览

    <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.userName}"/>
    

    android.text = "@{user.userName}",使用@{}即可取user中的值,这个user就是顶部定义的绑点数据啦,到这里,我开始思考,这个user是不是到时候我在我的Activity中进行绑点操作就可以直接显示到我的界面了啊。bingo,废话,不然叫数据绑定啊。

    Activity中绑定

    有了布局文件,有了需要绑点的数据,怎么在将其进行绑定了,说白了,我界面需要使用user这个对象,我总得初始化吧。
    很简单了,在Activity中,创建两个全局变量

    ActivityJetpackBinding binding;
    User user;
    

    这里user没什么好说了,那个ActivityJetpackBinding是什么鬼,说一下我的Activity名字叫JetpackActivity,so,这个类就是前面我说的自动生成的啦,怎么实例化呢。

    binding = DataBindingUtil.setContentView(this,R.layout.activity_jetpack);
    

    使用DataBindingUtil就可以了,咦,这个setContentView好熟悉,一般onCreate中都有这个,一想到绑定,难道这句话会把之前的那个setContentView也干掉了,我小心翼翼的去掉之前的setContentView,果然可以运行,那怎么干掉的呢(其实不用看,我只是好奇怎么干掉的,所以看看源码),

    点进去看到

    public static <T extends ViewDataBinding> T setContentView(Activity activity, int layoutId) {
            return setContentView(activity, layoutId, sDefaultComponent);
        }
    

    再点return后面的setContentView

    public static <T extends ViewDataBinding> T setContentView(Activity activity, int layoutId,
                DataBindingComponent bindingComponent) {
            activity.setContentView(layoutId);
            View decorView = activity.getWindow().getDecorView();
            ViewGroup contentView = (ViewGroup) decorView.findViewById(android.R.id.content);
            return bindToAddedViews(bindingComponent, contentView, 0, layoutId);
        }
    

    ok,熟悉的 activity.setContentView(layoutId);
    说明确实干掉了。

    得到了binding对象,新建一个User,怎么将新建的User和binding联系起来呢
    原来binding有setter和getter啦binding.setUser(user);,就这样,运行时,TextView的值有了,全程没有使用之前的setTex(),完整一点的onCreate代码

    //        setContentView(R.layout.activity_jetpack);
            binding = DataBindingUtil.setContentView(this,R.layout.activity_jetpack);
            user = new User("家佳",25);
            binding.setUser(user);
    

    到这里,基本的绑定就实现了,算是入门了吧,来看看和之前的区别,布局文件中没有id,activity中没有绑定id,没有setText,确实看起来少了许多。But.....

    这肯定不是我要的效果啊,我要的是改变user的值,界面跟着改变,不用去setText
    所以我开始思考

    思考

    如果我改变User的值,界面会跟着变吗?其实肯定会的,只是我还不知道怎么用,我的想法很单纯,很简单,搞个Button,点击需改全局User的值,界面跟着变,ok,我写了,然而打了自己的脸,我怎么这么可爱,too young 以为 很simple。
    那么怎么才能实现这个效果呢。

    动态绑定

    原来需要再User这个类上下功夫
    数据绑定提供了基类BaseObservable,需要继承它,修改后的User如下

    
    public class User extends BaseObservable{
        private String userName;
        private int age;
        public User(String userName, int age) {
            this.userName = userName;
            this.age = age;
        }
        @Bindable
        public String getUserName() {
            return userName == null ? "" : userName;
        }
        public void setUserName(String userName) {
            this.userName = userName;
            notifyPropertyChanged(BR.userName);
        }
        @Bindable
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
            notifyPropertyChanged(BR.age);
        }
    }
    

    在getter上面加@Bindable,在setter函数中加notifyPropertyChanged,好熟悉Adapter啊,一看这个实现应该是观察者模式啦。这里notifyPropertyChanged需要一个int参数,查看一番,据说类似R.java中的id一样,不懂,看别人用的BR,直接用BR即可,关于BR是啥,还不知道。
    更改了User类之后,在之前的button中通过user.setUsername(),完美实现了布局中数据的改变。

    最后

    数据绑定还有很多东西,比如动态绑定,不需要这么麻烦,比如Button的onClick事件也可以绑定,下篇再说把。

    此致,敬礼

  • 相关阅读:
    java之扩展运算符
    error LNK2005: _DllMain@12 已经在 dllmain.obj 中定义
    MinGW
    Gcc/MinGW/Cygwin/Msys 分别是什么?
    开源项目:windows下使用MinGW+msys编译ffmpeg
    MinGW安装和使用基础教程
    基于UDP高性能传输协议UDT doc翻译(一)
    基于UDT connect连接通信以及文件传输--客户端
    基于UDT connect连接通信以及文件传输--服务端
    FreeSWITCH第三方库(其他)的简单介绍(三)
  • 原文地址:https://www.cnblogs.com/numen-fan/p/11068358.html
Copyright © 2011-2022 走看看