Android: Databinding笔记

关于databinding

databinding,即数据绑定。google帮助我们在android上实现mvvm的一个框架。具体的MVVM我理解不深,可以看下这篇文章:Android DataBinding:再见Presenter,你好ViewModel!
不过从个人感觉上,databinding确实让代码简洁了很多,更新数据的工作也没有这么繁琐了。
下面是我的学习笔记边学边记。遇到的错误也会记录下来。我没说到的知识点,可以带上梯子到Data Binding Library看。

配置

1,首先,Gradle版本需要1.5.0-alpha1以上。

2,如果Android Studio版本大于1.5,那只需要在对应的module的build.gradle中添加

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

3,如果Android Studio的版本小于1.5,大于1.3,在project中加入依赖:

classpath 'com.android.tools.build:gradle:1.2.3'
classpath 'com.android.databinding:dataBinder:1.0-rc0'

修改对应module的build.gradle

apply plugin: 'com.android.databinding'

建立数据源

都说是数据绑定,我们首先需要一个java bean类作为数据源。

我们可以简单地建一个user类

public class User {
    private String userName;
    private int age;

    public User(String userName, int age){
        setUserName(userName);
        setAge(age);
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

实际上,DataBinding读写数据的时候,是调用get/set方法的。如果不定义变量,只写get/set方法也是可行的。

public class User {

    public String getUserName() {
        return "xiao xin";
    }

    public void setUserName(String userName) {
    }

    public int getAge() {
        return 33;
    }

    public void setAge(int age) {
    }
}


数据更新的时候,view同步更新。

1.让数据源的类继承BaseObservable类,并且在需要更新的时候调用notifyPropertyChanged()方法。
代码中的BR是databinding生成的对应数据源的静态变量。和R.id同理。

private static class User extends BaseObservable {
   private String firstName;
   private String lastName;
   @Bindable
   public String getFirstName() {
       return this.firstName;
   }
   @Bindable
   public String getLastName() {
       return this.lastName;
   }
   public void setFirstName(String firstName) {
       this.firstName = firstName;
       notifyPropertyChanged(BR.firstName);
   }
   public void setLastName(String lastName) {
       this.lastName = lastName;
       notifyPropertyChanged(BR.lastName);
   }
}

2.可以直接把变量定义为ObservableFields类型的变量,那样每次变量的值发生变化,view也会同步刷新。

private static class User {
   public final ObservableField<String> firstName =
       new ObservableField<>();
   public final ObservableField<String> lastName =
       new ObservableField<>();
   public final ObservableInt age = new ObservableInt();
}

一个,特别的,Observable类型的集合 --> ObservableArrayMap
定义和普通的map差不多

ObservableArrayMap<String, Object> user = new ObservableArrayMap<>();
user.put("firstName", "Google");
user.put("lastName", "Inc.");
user.put("age", 17);

在layout中使用:

<data>
    <import type="android.databinding.ObservableMap"/>
    <variable name="user" type="ObservableMap<String, Object>"/>
</data>
…
<TextView
   android:text='@{user["lastName"]}'
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>
<TextView
   android:text='@{String.valueOf(1 + (Integer)user["age"])}'
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

布局

用了Data Binding的布局文件布局就要变一变了。根元素是一个layout节点。layout节点下面是data节点和原来布局文件的根节点。

格式如下:

<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
    </data>
    
    <!--用DataBinding之前的根节点-->
    <LinearLayout>
    ...
    </LinearLayout>
</layout>

如果要使用user类中的数据,可以这样写

<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
 
        <!--定义了一个User类的变量-->
        <variable
            name="user"
            type="com.test.db.User" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <!--通过@{user.userName},直接把user里的userName变量的数据写入textview-->
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.userName}" />
    </LinearLayout>

</layout>

DataBinding还是挺智能的,如果某些变量没有赋值,会自动赋一个空值。

相同名字的类

如果有两个相同名字的类,我们可以这样

<data>
    <import
        alias="TrueUser"
        type="com.ehang.databindingtest.bean.User" />

    <import
        alias="FakeUser"
        type="com.ehang.databindingtest.User" />
        
    <variable
        name="user"
        type="TrueUser" />

    <variable
        name="user2"
        type="FakeUser" />
</data>

然后分别调用user和user2两个变量就好了。

其他数据类型的变量

我们还可以定义String,int,map等变量

<data>
    <import type="java.util.ArrayList" />

    <import type="java.util.HashMap" />
    
    <variable
        name="list"
        type="ArrayList" />

    <variable
        name="map"
        type="HashMap" />
        
    <variable
        name="str"
        type="String" />

    <variable
        name="boo"
        type="boolean" />

    <variable
        name="num"
        type="int" />
</data>

定义好的变量可以在实际的布局中使用了。

运算符

Data Binding还支持大多数的运算符。加减乘除,字符合并,逻辑云算法,二元三元等等。
下面是一个三元元算符的例子。

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text='@{boo?"true": "false"}'/>

数据绑定

需要在activity中对数据进行绑定。即把数据源和布局关联起来。

public class MainActivity extends AppCompatActivity {

    private User mUser;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //注意,这里已经没有setContentView()方法了。
        ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);

        mUser = new User("xiao xin", 33);
        binding.setUser(mUser);
    }
}

至此,就完成了一个简单的DataBinding了。

动态添加view时,使用databinding

每一个使用了databinding的布局,都会自动生成一个ViewDatabinding的子类。在例子中,布局R.layout.layout3使用了databinding,从而生成了Layout3Binding类。我们可以通过这个类的 bind(布局实例) 方法来进行数据绑定。

 RelativeLayout.LayoutParams relativeLayoutParams = new RelativeLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);

    ViewGroup layout1 = (ViewGroup) LayoutInflater.from(this).inflate(R.layout.layout3, null);
    
    rootLayout.addView(layout1, relativeLayoutParams);
    
    Layout3Binding binding1 = Layout3Binding.bind(layout1);

    binding1.setData(data);

替换字符

在string.xml中

    <string name="util">%1$s千克 %2$s米</string>

其中有两个替换字符。

布局文件中

android:text="@{String.format(@string/util,model.weight,`123`)}"

util中的字符串中的替换字符分别替换成model.height和123。显示的结果会是“weight的值 千克 123米”

如果只有一个替换字符时,用

    <string name="util">%s米</string>

include

给include进来的布局绑定数据,可以这样:

<include layout="@layout/name"
    bind:user = "@{user}"/>

某个布局用了databinding,这个布局include的所有布局都要用databinding

include进来的是一个databindiing布局,并不能拿来做动画操作。比如布局a中include了布局b,对b做动画,不能直接使用databinding.b,要用databinding.b.b布局的父布局。

import

有些时候我们需要用到其他工具类的静态方法,或者直接拿一个bean的单例来做数据绑定,我们需要先import一下。

同样是在data标签里面:

 <import type="com.ehang.communication.ViewModel.HudInfoViewModel"/>

然后就可以使用了

 android:text="@{HudInfoViewModel.getInstance().altitude}"

databinding类不存在的错误

databinding绑定的数据源,如果返回的是一个数字,那就会报这个错误

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,905评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,140评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,791评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,483评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,476评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,516评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,905评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,560评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,778评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,557评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,635评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,338评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,925评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,898评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,142评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,818评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,347评论 2 342

推荐阅读更多精彩内容