DataBinding与MVVM(含代码)

DataBinding是对MVVM架构的最好诠释,一直以来逻辑,数据模型,和界面之间的关系都没有一个很好的平衡,MVP架构会使大量的逻辑代码都集中在Presenter中,而DataBinding可以很好的平衡这些之间的关系

工程配置

之前看到网上许多资料都是需要配置DataBinding的依赖,但是我使用的是新版的gradle,没有出现需要配置依赖的地方,只需要在gradle(app的gradle)中加入以下代码:

dataBinding {   
 enabled true
}

数据对象的绑定

首先新建一个工程,有一个MainActivity以及一个activity_main.xml的布局文件,当然你叫别的名字也无所谓。然后建一个数据模型类,如下:

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

然后修改布局文件activity_main.xml

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

    <data>

        <import type="databind.android.com.testdatabind.Person" />

        <variable
            name="animal"
            type="databind.android.com.testdatabind.Animal" />

        <variable
            name="person"
            type="Person" />

        
    </data>

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

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{person.name}"
            android:textColor="#000000"
            android:textSize="18dp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{person.age}"
            android:textColor="#000000"
            android:textSize="14dp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{person.sex}"
            android:textColor="#000000"
            android:textSize="14dp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{animal.name}"
            android:textColor="#000000"
            android:textSize="18dp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{animal.age}"
            android:textColor="#000000"
            android:textSize="14dp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{animal.sex}"
            android:textColor="#000000"
            android:textSize="14dp" />

      
    </LinearLayout>
</layout>

与以往的布局文件不同的是,这类布局文件会有一个data的标签,import的语法与java一样,不过多介绍,variable便是一个变量,在布局文件中定义变量,是不是很稀奇,这正是data binding的核心所在。
接下来我们在对应的activity中添加如下代码:

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        Person person =  new Person("umeng share","5");
        Animal animal = new Animal("cat","5");
        binding.setPerson(person);
        binding.setAnimal(animal);
        person.setSex("male");
        animal.setSex("female");
    }

ActivityMainBinding这个类是根据刚才的布局文件自动生成的,因为刚才布局文件叫activity_main所以自动生成类ActivityMainBinding,如果叫activity_ddd,就会自动生成ActivityDddBinding。
此时运行程序,就会显示对应的字符,没有了findviewbyid是不是清晰多了。

点击事件

如果你认为只有这些功能,那就大错特错了,接下来再看一下如何添加点击事件。
布局中添加如下代码(在哪添加不用说了吧,当然是data标签下):

 <variable
            name="click"
            type="android.view.View.OnClickListener" />

以及布局中添加:

 <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{click}"
            android:textColor="#000000"
            android:textSize="14dp" />

同时我们在Activity中添加如下代码:

binding.setClick(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
           
            }
        });

通过以上两个例子可以看出我们可以在java代码中通过binding设置变量的具体内容,然后在布局文件中接受变量的内容,然后通过布局显示出来。

其它类型

除此之外,所有java的集合类数据类型,都可以支持,比如List
我们修改布局文件:

<import type="java.util.ArrayList" />
<variable
            name="list"
            type="ArrayList&lt;String>" />

        <variable
            name="listKey"
            type="int" />
<TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{click}"
            android:text="@{list[listKey]}"
            android:textColor="#000000"
            android:textSize="14dp" />

对应的java代码:

binding.setList(list);
binding.setListKey(0);

要注意的是布局文件中<符号会被转义,所以我们用<,在布局文件中会报红,但是不影响编译

方法的调用

我们新建一个方法类:

public class StringUtil {
    public static String cut( String word) {
       if (word.length()>4){
           word = word.substring(0,4);

       }
        return word;
    }
}

在布局文件中可以用如下方式调用:

<import type="databind.android.com.testdatabind.StringUtil" />
 <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{StringUtil.cut(person.name)}" />

检测变量的变化

在实际应用中,所有的变量不可能是一成不变的,如果变量的值发生变化如何在界面上更新呢?
我们需要修改一下数据模型类:

package databind.android.com.testdatabind.detail;

import android.databinding.BaseObservable;
import android.databinding.Bindable;

import databind.android.com.testdatabind.BR;

/**
 * Created by wangfei on 17/1/1.
 */
public class Person  extends BaseObservable {
    private String name;
    private String age;
    private String sex;
    public Person(String name, String age) {
        this.name = name;
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
        notifyPropertyChanged(BR.name);
    }

    public void setAge(String age) {
        this.age = age;
        notifyPropertyChanged(BR.age);
    }
    @Bindable
    public String getName() {
        return this.name;
    }
    @Bindable
    public String getAge() {
        return this.age;
    }

    public void setSex(String sex) {
        this.sex = sex;
        notifyPropertyChanged(BR.sex);
    }
    @Bindable
    public String getSex() {
        return sex;
    }
}

在get方法中加上注解@Bindable,同时在set方法中加入 notifyPropertyChanged(BR.xxx);
同时在java文件中,需要变动的地方,直接设置变量的值即可触发界面的变化:

person.setName("点击按钮产生了变化");

什么取代了findViewById

正常编程下我们都是通过findViewById获得布局文件中各组件的对象,那么在data binding下如何获取呢?
其实非常简单,例如有如下布局:

  <TextView
            android:id="@+id/mutable"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{realperson.sex}"
            android:textColor="#000000"
            android:textSize="14dp" />

ID是mutable,那么在java文件中的binding会自动生成对应的变量mutable

binding.mutable.setText("点击事件");

表达式

除此之外,还可以在布局文件中运用一些基本的表达式,如下:

<TextView
   android:text="@{person.sex}"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:visibility="@{person.isMan ? View.VISIBLE : View.GONE"/>

总结

除了上面介绍的基本方法,data Binding当然还有很多高级方法,我们需要在实际应用中去学习,这里只做了简单的介绍,但是不难看出,如果这种方式使用纯熟了,开发界面类应用真的会省去很多麻烦。
我在这里写了一个简单的demo,感兴趣的朋友可以参考一下:
https://github.com/mymdeep/databinding

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

推荐阅读更多精彩内容