DataBinding的用法

DataBinding的用法

  • 是时候抛弃ButterKnife,拥抱DataBinding了。
    1.ButterKnife对组件化方案支持不如DataBinding
    2.ButterKnife只支持View绑定,不支持数据绑定
    3.DataBinding是Google出品。
    就算只看第三条,你也知道选哪个了吧 (手动滑稽)下面还有更多DataBinding的优点

启用DataBinding

android {
    dataBinding {
        enabled true
        }
}

***注意:如在lib中也使用DataBinding也需要在build文件中添加 ***

DataBinding 的基本使用

数据绑定

我们创建一个User类,User有两个属性:name和age。

public class User {
    private String name;
    private int age;
    public User() {
        this.name = "小花";
        this.age = 18;
    }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
}

也可以这样写

public class User {
    public String name;
    public int age;
}

然后我们想把User这个对象的两个属性绑定在xml控件中,我们创建一个activity_main.xml文件.因为age属性是int类型,而textView.setText()不允许使用int,所以,我们可以在后面拼上字符标志``

<?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.ding.databindingdemo.User" />
    </data>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.name}" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.age+`岁`}" />
    </LinearLayout>
</layout>

然后我们在Activity中获取xml对应的DataBinding对象,并对其进行赋值

    private ActivityMainBinding mBinding;//这个对象是根据activity_main.xml命名规则自动生成的,继承自ViewDataBindig了;类
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBinding = DataBindingUtil.setContentView(this,R.layout.activity_main);
        mBinding.setVariable(BR.user,new User());
        //或者
        mBinding.setUser(new User());
        mBinding.executePendingBindings();
    }

fragment这样绑定DataBindingUtil.inflate(inflater,R.layout.fragment_home,container,false);

是不是很简单?这还简单的,看的我头皮发麻,两眼发晕,我不需要绑定什么数据,我就想跟ButterKnife用法一样。好,下面就满足你

控件绑定

我们在xml中为每个你需要拿到的控件命名ID

        <Button
            android:id="@+id/main_btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

那我们应该怎么拿到对应的控件呢?就是我们的ViewDataBinding的子类,生成的ActivityMainBindingButton mBinding.mainBtn(生成规则遵循Java驼峰命名),这样我们就可以拿到这个按钮了,之后的事情就不用我说了把。

方法绑定

        <Button
            android:id="@+id/main_btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" 
            android:onClick="onClick"/>

以前我们可以这样写点击事件,然后在activity中定义public void onClick(View view) { }方法,然后在这里面对点击事件进行处理。现在,我们可以对这个点击事件做任何方法的跳转。传入类,mBinding.setVariable(BR.act,this);然后传入类方法android:onClick="@{()->类对象.类方法(参数para)}"

        <variable
            name="act"
            type="com.example.ding.databindingdemo.MainActivity"/>
        <Button
            android:id="@+id/main_btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" 
            android:onClick="@{()->act.getName(user.name)}"/>

我们在activity中定义的方法public void getName(String name){ //todo }。当然,你也可以导入其他类。例如定义MyHandlers

public class MyHandlers {
    public void getName(String name) { ... }
}

布局文件就要这样写。

    <variable
            name="handler"
            type="com.example.ding.databindingdemo.MyHandlers"/>
        <Button
            android:id="@+id/main_btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" 
            android:onClick="@{()->handler.getName(user.name)}"/>

注意:要在Activity中传入MyHandlers实例,不然会报空指针。

自定义方法Binding adapters

有些控件不能直接传数据就能展示,例如ImageView,RecyclerView之类。我们可以用BindingAdapter注解来自定义方法,xml中使用方式:

<ImageView 
       android:layout_width="wrap_content"
       android:layout_height="wrap_content" 
       bind:imageUrl="@{user.pic}" />

新建一个java类,类名随意。类方法需为static@BindingAdapter注解标记该方法,valueStirng[],xml中使用的atts与里面的命名规则一致。requireAll是否必须传。然后在setImageUrl方法中获取view和url参数,然后进行展示。当然url也可以替换为src或者bitmap

public class ImageBindingAdapter {
    @BindingAdapter(value = {"bind:imageUrl"},requireAll = true)
    public static void setImageUrl(ImageView view,String url){ 
        Glide.with(view.getContext()).load(url).into(view);
    }
   @BindingAdapter(value = {"bind:imageSrc"},requireAll = true)
    public static void setImageSrc(ImageView view,int src){
        view.setImageResource(src);
    }
    @BindingAdapter(value = {"bind:imageBitmap"},requireAll = true)
    public static void setImageBitmap(ImageView view,Bitmap bitmap){
        view.setImageBitmap(bitmap);
    }
}

假如你写了一个自定义控件,你也可以用@BindingAdapter绑定你的数据源。例如,我写了一个MyLinearLayout来实现ListView,然后我写了一个text_list方法来传递数据。

<com.ding.example.MyLinearLayout 
       android:layout_width="wrap_content"
       android:layout_height="wrap_content" 
       bind:text_list="@{user.datas}" />

java代码

public class LinearLayoutBindingAdapter {
    @BindingAdapter(value = {"bind:text_list"},requireAll = true)
    public static void setDataResource(MyLinearLayout layout,List datas){ 
        layout.setDataList(datas);
    }

这样,我们就把数据源传到我们的MyLinearLayout中,然后在我们自定义的LinearLayout中对数据做处理了。

双向绑定

双向绑定使用@={}就可以实现了。没错,就是这么简单。例如,EditText中双向绑定了user.job这个属性,当editText中内容发生更改时,绑定的数据user.job也会更新,通过mBinding.getUser().job就可以拿到最新的数据了。

表达式

  • 数学运算符: + - / * %
  • 字符串拼接: +
  • 逻辑运算符: && ||
  • 二进制: & | ^
  • 一元运算符: +
  • 位运算符: >> >>> <<
  • 比较: == > < >= <=
  • instanceof
  • ()<
  • 数据类型: character, String, numeric, null
  • 类型转换(ClassCast)
  • 方法回调(Method calls)
  • 数据属性
  • 数组:[]
  • 三元操作符:?

与LiveData连用

LiveData是谷歌新推出的一个可被观察的数据持久化的控件,通常出现在ViewModel中,是用用MVVM架构。有兴趣的看一下我的上一篇文章基于Google MVVM框架的baseMVVM框架
LiveData遵循其他应用程序控件的生命周期,例如Activity,Fragment或Service。此感知确保LiveData仅更新处于活动生命周期状态的应用程序控件观察者,不会造成内存泄漏。具体是用请参考官方文档

  • 注意:DataBinding需调用setLifecycleOwner(LifecycleOwner lifecycleOwner)之后,绑定了LiveData数据源的xml控件才会随着数据变化而改变。
  • 注意:LiveData暴露公开两个方法用于设置值:
    1.postValue:允许后台线程向主进程推送数据
    2.setValue:只允许在主线程调用,如果在其他线程调用会报错:This method must be called from the main thread
    最后奉上demo的github地址 https://github.com/dingdaidao/DataBindingDemo
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,496评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,407评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,632评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,180评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,198评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,165评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,052评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,910评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,324评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,542评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,711评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,424评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,017评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,668评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,823评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,722评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,611评论 2 353

推荐阅读更多精彩内容