數(shù)據(jù)綁定框架DataBinding--入門篇

一、描述

MVC,MVP都是大家所熟知的,而今天的主題的MVVM數(shù)據(jù)綁定,這個是最新推出的框架,剛加入公司沒多久,看公司里的同事再用這個,所以我熟悉之后發(fā)現(xiàn)確實挺好用的,在這里分享給大家。

二、引用

Data Binding自從去年的Google I/O發(fā)布到至今,也有近一年的時間了。這一年來,從Beta到如今比較完善的版本,從Android Studio 1.3到如今2.1.2的支持,可以說Data Binding已經(jīng)是一個可用度較高,也能帶來實際生產(chǎn)力提升的技術(shù)了。

而事實上,真正使用到Data Binding的公司、項目仍然是比較少的。可能是出于穩(wěn)定性考慮,亦或是對Data Binding技術(shù)本身不夠熟悉,又或許對新技術(shù)沒什么追求。

我司在新的產(chǎn)品中就全面使用了Data Binding技術(shù),無論是我,還是新來直接面對Data Binding上手的工程師也好,都對其愛不釋手,用慣了后簡直停不下來。

希望在看完本文的介紹后,會有更多的朋友產(chǎn)生興趣,來使用Data Binding,參與它的討論。

三、什么是DataBinding

這里我以我的理解來說,就是一個或者多個實體對象對應(yīng)著一個頁面,實體中的某些屬性綁定著頁面上的控件,當(dāng)屬性的值改變時,頁面上的控件會自動更新數(shù)據(jù)。

四、效果展示

沒用DataBinding之前

XML布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.junwen.databinding.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:text="姓名:" />

        <TextView
            android:id="@+id/activity_main_stu_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:text="學(xué)生姓名" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:text="年齡:" />

        <TextView
            android:id="@+id/activity_main_stu_age"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:text="學(xué)生年齡" />
    </LinearLayout>


    <Button
        android:id="@+id/activity_main_stu_setting"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="更改姓名" />
</LinearLayout>

Student實體類


/**
 * 描述:學(xué)生對象
 * 作者:卜俊文
 * 創(chuàng)建:2016/8/10 10:20
 * 郵箱:344176791@qq.com
 */
public class Student {
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    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;
    }
}



MainActivity主頁面



public class MainActivity extends AppCompatActivity {

    private TextView tv_name; //學(xué)生姓名
    private TextView tv_age; //學(xué)生年齡
    private Button btn_setting; //設(shè)置
    private Student student; //學(xué)生對象

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initData();
        initListener();
    }


    /**
     * 描述:初始化控件
     * 作者:卜俊文
     * 郵箱:344176791@qq.com
     * 創(chuàng)建時間: 2016/8/10 10:17
     */
    private void initView() {
        tv_name = (TextView) findViewById(R.id.activity_main_stu_name);
        tv_age = (TextView) findViewById(R.id.activity_main_stu_age);
        btn_setting = (Button) findViewById(R.id.activity_main_stu_setting);
    }

    /**
     * 描述:初始化數(shù)據(jù)
     * 作者:卜俊文
     * 郵箱:344176791@qq.com
     * 創(chuàng)建時間: 2016/8/10 10:19
     */
    private void initData() {
        //創(chuàng)建一個學(xué)生對象
        student = new Student("俊文", 22);
        //根據(jù)學(xué)生對象賦值到控件上
        tv_name.setText(student.getName());
        tv_age.setText(String.valueOf(student.getAge()));
    }

    /**
     * 描述:初始化監(jiān)聽
     * 作者:卜俊文
     * 郵箱:344176791@qq.com
     * 創(chuàng)建時間: 2016/8/10 10:22
     */
    private void initListener() {
        btn_setting.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //點擊設(shè)置,更改Student對象的名字。
                student.setName("卜俊文");
                tv_name.setText(student.getName());
            }
        });
    }

}


運用DataBinding

XML布局

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

    <data>

        <variable
            name="student"
            type="com.example.junwen.databinding.Student" />
    </data>

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

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dp"
                android:text="姓名:" />

            <TextView
                android:id="@+id/activity_main_stu_name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dp"
                android:text="@{student.name}" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dp"
                android:text="年齡:" />

            <TextView
                android:id="@+id/activity_main_stu_age"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dp"
                android:text="@{String.valueOf(student.age)}" />
        </LinearLayout>


        <Button
            android:id="@+id/activity_main_stu_setting"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="更改姓名" />
    </LinearLayout>
</layout>  

Student實體類



/**
 * 描述:學(xué)生對象, @Bindable注解是為了能在BR里面找到這個屬性     notifyPropertyChanged();  這個方法是當(dāng)調(diào)用的時候,會通知綁定的控件去改變值
 * 作者:卜俊文
 * 創(chuàng)建:2016/8/10 10:20
 * 郵箱:344176791@qq.com
 */
public class Student extends BaseObservable {

    @Bindable
    private String name;

    @Bindable
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        notifyPropertyChanged(com.example.junwen.databinding.BR.name);
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
        notifyPropertyChanged(com.example.junwen.databinding.BR.age);
    }
}

MainActivity主頁面



public class MainActivity extends AppCompatActivity {


    private ActivityMainBinding activity_main_binding; //本頁面的Binding對象
    private Student student; //學(xué)生對象

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();
        initListener();
    }

    /**
     * 描述:初始化數(shù)據(jù)
     * 作者:卜俊文
     * 郵箱:344176791@qq.com
     * 創(chuàng)建時間: 2016/8/10 10:48
     */
    private void initData() {
        //這個就類似于setContentView
        activity_main_binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        student = new Student("俊文", 22);
        //把Student對象綁定到布局的控件中去,現(xiàn)在開始只要student對象屬性變化,控件的值也是相應(yīng)改變
        activity_main_binding.setStudent(student);
    }

    /**
     * 描述:初始化監(jiān)聽
     * 作者:卜俊文
     * 郵箱:344176791@qq.com
     * 創(chuàng)建時間: 2016/8/10 10:22
     */
    private void initListener() {
        activity_main_binding.activityMainStuSetting.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                student.setName("卜俊文");
            }
        });
    }

}

五、優(yōu)劣所在?

優(yōu)勢

(1) DataBinding不需要findviewbyId,只需要根據(jù)binding對象去查找到對應(yīng)的控件。

(2)直接綁定一個對象到XML布局中,當(dāng)對象的屬性變化時,布局中的控件會馬上同步變化。

(3)UI代碼放到了xml中,布局和數(shù)據(jù)更緊密

劣勢

(1)IDE支持還不那么完善(提示、表達式)

(2)報錯信息不那么直接

六、開始編寫

(1) 在app / build.gradle 中加入以下字段,即可使用DataBinding框架

dataBinding {   
 enabled = true
}

(2)編寫XML,這里給出一個XML模版

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

    <data>

        <variable
            name="item"
            type="com.example.junwen.databinding.Student" />
    </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="@{item.name}" />
    </LinearLayout>
</layout>  

此模塊由<Layout>標(biāo)簽作為根節(jié)點,里面包含兩部分,第一部分是<data>,第二部分就是<LinearLayout>,也就類似于以前我們寫布局時的根布局。

其中<data>標(biāo)簽中可以聲明對象,變量以及導(dǎo)入包等功能,在這里我導(dǎo)入了Student對象,在下面我需要用到我就可以導(dǎo)入進來,并且起成item的一個別名。

其中<LinearLayout>中,包含了一個TextView,這個TextView的text屬性值是這樣賦值的(格式必須對):

android:text="@{item.name}"

雙引號中 " @{具體變量或者對象的屬性值}" ,不只這些,還可以在里面運用表達式,例如上面的例子中的

 android:text="@{String.valueOf(student.age)}"

這個能夠在一個屬性的后面添加字符串比如下面

android:text="@{item.progress+`%`}"

(3)編寫MainActivity

(1)取得Binding對象,這個就類似于setContentView(),返回的對象其實是一個ViewDataBinding,但是我這里寫的是ActivityMainBinding,你可以比較一下ActivityMainBinding 和 R.layout.activity_main有什么相似的地方嗎?不錯,就是拼接起來的,這樣就可以獲得這個頁面的Binding對象。

ActivityMainBinding activity_main_binding = DataBindingUtil.setContentView(this, R.layout.activity_main);

(2)創(chuàng)建一個Student對象,并且調(diào)用setStudent(student)方法,這個方法他會自動生成的,實現(xiàn)了實體與xml綁定。

Student student = new Student("俊文", 22);
//把Student對象綁定到布局的控件中去,現(xiàn)在開始只要student對象屬性變化,控件的值也是相應(yīng)改變
activity_main_binding.setStudent(student)

(3)設(shè)置監(jiān)聽,直接通過binding對象查詢到按鈕控件,這個activityMainStuSetting也會自動生成的,如果遇到?jīng)]有生成,你需要build一下項目,他就會出來了,執(zhí)行setName方法,在其內(nèi)部就會去通知控件更新文本。

activity_main_binding.activityMainStuSetting.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                student.setName("卜俊文");
            }
        });

七、其他

操作符示例:

(1)判斷屬性賦值不同的圖片

android:src="@{item.checkState.equals(String.valueOf(3)) ? @drawable/ic_task_exit :  @drawable/ic_task_success }" 

(2)設(shè)置不同的字符串

android:text='@{error ? "error" : "ok"}'

XML的DataBinding模版XML快速創(chuàng)建

1229.gif

關(guān)于DataBinding數(shù)據(jù)綁定

Android官方數(shù)據(jù)綁定框架DataBinding

從零開始的Android新項目7 - Data Binding入門篇

Android官方數(shù)據(jù)綁定框架DataBinding(一)

Android Data Binding代碼實戰(zhàn)

完全掌握Android Data Binding

數(shù)據(jù)綁定DataBinding

八、總結(jié)

在此就總結(jié)了一些基本的DataBind的用法,可能有些地方說的不到位的,也是剛接觸不是很熟悉,就是憑自己的理解來說的。

歡迎關(guān)注我的微信公眾號,分享更多技術(shù)文章。

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

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,725評論 25 709
  • 參考自一葉飄舟 Android新推出了一個官方的數(shù)據(jù)綁定框架Data Binding Library,既然是官方推...
    劉滌生閱讀 6,596評論 4 24
  • 妮兒: 再有十二天你就十一歲了,媽媽今天才第一次給你寫信! 我如此的渴望有個女兒,卻沒想到我和我的女兒之間能有那么...
    Simple_mw閱讀 688評論 0 2
  • 我們總管不住自己的手。。。 VS的啟動時發(fā)生錯誤的對話框點了不再提示后又迅速點了確定。。 要是不知道怎么恢復(fù),只能...
    lack倪醬閱讀 1,504評論 0 0
  • 我想你,在最深的夜里 那里有著我們的過去 我想你,在過去的記憶里 那里還有著你存在的痕跡 可是呀,我現(xiàn)在也只能想想...
    幻夢邪魂閱讀 412評論 0 2

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