DataBinding與MVVM(含代碼)

DataBinding是對(duì)MVVM架構(gòu)的最好詮釋,一直以來邏輯,數(shù)據(jù)模型,和界面之間的關(guān)系都沒有一個(gè)很好的平衡,MVP架構(gòu)會(huì)使大量的邏輯代碼都集中在Presenter中,而DataBinding可以很好的平衡這些之間的關(guān)系

工程配置

之前看到網(wǎng)上許多資料都是需要配置DataBinding的依賴,但是我使用的是新版的gradle,沒有出現(xiàn)需要配置依賴的地方,只需要在gradle(app的gradle)中加入以下代碼:

dataBinding {   
 enabled true
}

數(shù)據(jù)對(duì)象的綁定

首先新建一個(gè)工程,有一個(gè)MainActivity以及一個(gè)activity_main.xml的布局文件,當(dāng)然你叫別的名字也無所謂。然后建一個(gè)數(shù)據(jù)模型類,如下:

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>

與以往的布局文件不同的是,這類布局文件會(huì)有一個(gè)data的標(biāo)簽,import的語法與java一樣,不過多介紹,variable便是一個(gè)變量,在布局文件中定義變量,是不是很稀奇,這正是data binding的核心所在。
接下來我們?cè)趯?duì)應(yīng)的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這個(gè)類是根據(jù)剛才的布局文件自動(dòng)生成的,因?yàn)閯偛挪季治募衋ctivity_main所以自動(dòng)生成類ActivityMainBinding,如果叫activity_ddd,就會(huì)自動(dòng)生成ActivityDddBinding。
此時(shí)運(yùn)行程序,就會(huì)顯示對(duì)應(yīng)的字符,沒有了findviewbyid是不是清晰多了。

點(diǎn)擊事件

如果你認(rèn)為只有這些功能,那就大錯(cuò)特錯(cuò)了,接下來再看一下如何添加點(diǎn)擊事件。
布局中添加如下代碼(在哪添加不用說了吧,當(dāng)然是data標(biāo)簽下):

 <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" />

同時(shí)我們?cè)贏ctivity中添加如下代碼:

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

通過以上兩個(gè)例子可以看出我們可以在java代碼中通過binding設(shè)置變量的具體內(nèi)容,然后在布局文件中接受變量的內(nèi)容,然后通過布局顯示出來。

其它類型

除此之外,所有java的集合類數(shù)據(jù)類型,都可以支持,比如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" />

對(duì)應(yīng)的java代碼:

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

要注意的是布局文件中<符號(hào)會(huì)被轉(zhuǎn)義,所以我們用<,在布局文件中會(huì)報(bào)紅,但是不影響編譯

方法的調(diào)用

我們新建一個(gè)方法類:

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

       }
        return word;
    }
}

在布局文件中可以用如下方式調(diào)用:

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

檢測變量的變化

在實(shí)際應(yīng)用中,所有的變量不可能是一成不變的,如果變量的值發(fā)生變化如何在界面上更新呢?
我們需要修改一下數(shù)據(jù)模型類:

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,同時(shí)在set方法中加入 notifyPropertyChanged(BR.xxx);
同時(shí)在java文件中,需要變動(dòng)的地方,直接設(shè)置變量的值即可觸發(fā)界面的變化:

person.setName("點(diǎn)擊按鈕產(chǎn)生了變化");

什么取代了findViewById

正常編程下我們都是通過findViewById獲得布局文件中各組件的對(duì)象,那么在data binding下如何獲取呢?
其實(shí)非常簡單,例如有如下布局:

  <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會(huì)自動(dòng)生成對(duì)應(yīng)的變量mutable

binding.mutable.setText("點(diǎn)擊事件");

表達(dá)式

除此之外,還可以在布局文件中運(yùn)用一些基本的表達(dá)式,如下:

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

總結(jié)

除了上面介紹的基本方法,data Binding當(dāng)然還有很多高級(jí)方法,我們需要在實(shí)際應(yīng)用中去學(xué)習(xí),這里只做了簡單的介紹,但是不難看出,如果這種方式使用純熟了,開發(fā)界面類應(yīng)用真的會(huì)省去很多麻煩。
我在這里寫了一個(gè)簡單的demo,感興趣的朋友可以參考一下:
https://github.com/mymdeep/databinding

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容