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閱讀 230,501評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,673評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,610評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,939評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,668評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,004評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,001評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,173評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,705評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,426評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,656評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,139評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,833評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,247評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,580評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,371評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,621評論 2 380

推薦閱讀更多精彩內容