Android中MVVM模式

官方文檔地址:html

https://developer.android.com/intl/zh-cn/tools/data-binding/guide.htmljava

Data Binding Library有什麼用?android

每當有新東西出現咱們都喜歡問有什麼用?這可不是然並卵的東西,咱們來了解下。服務器

一、是官方支持的MVVM模式框架app

二、能夠直接在佈局 xml 文件中綁定數據,無需再 findViewById 而後手工設置數據框架

三、能夠提升解析XML的速度eclipse

四、UI與功能的解耦合ide

1、環境 佈局

在開始使用新東西以前,咱們須要稍微的配置一下環境,這裏要求你的Android Studio版本是1.3+,使用eclipse的同窗暫時尚未辦法使用該框架,請換用Android Studio。還有,在開始以前,請更新你的Support repository到最新的版本。 學習

萬事俱備,那咱們就開始搭配環境!

新建一個project,在dependencies中添加如下依賴

dependencies {
    classpath "com.android.tools.build:gradle:1.3.0"
    classpath "com.android.databinding:dataBinder:1.0-rc1"
}

因爲依賴的項目在 jcenter 服務器中,因此在repositories 中須要添加 jcenter以下:

allprojects {
   repositories {
       jcenter()
   }
}

在須要使用支持庫的module 的build.gradle文件中添加插件申請:

apply plugin: 'com.android.application'
apply plugin: 'com.android.databinding'

例子:如今作一個點擊一下按鈕而後年齡會+1的小功能,這裏也模擬了咱們是數據更新。

第一步:建立XML佈局

建立一個佈局xml文件,就像之前同樣。而後這裏咱們須要作一些少少的修改,在這個框架下咱們的思惟要稍稍改變一下了,之前的佈局XML只描述了佈局,他是相對固定的東西,在Data Binding Library下咱們的佈局XML就像是一個類,他能夠有變量也能進行必定的運算。其實Data Binding Library還真的給你生成了一個相似這樣的類。

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

    <data>
        <variable
            name="user"
            type="cn.golditfin.bean.User" />

        <variable
            name="buttonname"
            type="String" />
    </data>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.name}" />

        <TextView
            android:id="@+id/age_textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_centerHorizontal="true"
            android:text="@{String.valueOf(user.age)}" />

        <Button
            android:id="@+id/age_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:text="@{buttonname}" />

    </RelativeLayout>

</layout>

其中咱們佈局文件的根節點變成了layout,而後定義了變量。

在此佈局定義了:

一、兩個變量,一個是對象User,一個是String類型的buttonname。

二、兩個TextView一個Button

<data>
    <variable name="user" type="cn.golditfin.bean.User"/>
</data>

在 data 元素中使用 variable 來聲明在佈局文件中使用的變量。

name聲明瞭變量的名稱,type聲明瞭變量的類型,變量能夠爲基本類型如int,也能夠爲集合或者對象。

View中使用變量用@{} 格式來調用,下面Textview使用了咱們對象user的變量name。

<TextView
    android:id="@+id/textView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@{user.name}" />

第二步:定義數據對象

public class User {
 
    public String name;
 
    public int age;

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

很簡單就兩個成員變量

而後是Java代碼調用。

第三步:綁定數據

public class MainActivity extends AppCompatActivity {
 
    private User myUser;
 
    private ActivityMainBinding myBinding;
 
  
    @Override
 
    protected void onCreate(Bundle savedInstanceState) {
 
        super.onCreate(savedInstanceState);
 
        myBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
 
        myUser = new User("年齡",4);
 
        myBinding.setUser(myUser);
 
        myBinding.setButtonname("年齡+1");
 
        myBinding.ageButton.setOnClickListener(new View.OnClickListener() {
 
            @Override
 
            public void onClick(View v) {
 
                myUser.age++;
 
                myBinding.setUser(myUser);
 
            }
 
        });
 
    }

}

在Activity的onCreate方法中進行了基本的數據綁定。一句一句代碼給大家解釋。

一、原來設置佈局的setContentView方法咱們如今不用了,改爲了DataBindingUtil.setContentView

二、對於第一點的返回值是框架給咱們生成的類,該類按照單詞首字母大寫的規則,佈局的名字加上Binding組成。好比咱們的佈局是activity_main.xml,因此按照這個規則來轉換的話就變成了ActivityMainBinding。

三、自動生成的類ActivityMainBinding其實就是表明了那個佈局,裏面包括了佈局的View,咱們聲明的變量。咱們能夠經過這個對象獲取到佈局的元素。

四、binding.setUser(user);沒錯,這裏的setUser方法是框架給咱們自動生成的,每個佈局中聲明的變量都會自動生成對應的get,set方法。

好的,如今咱們跑起來看看。

如今已經實現咱們的想法了,可是看到這裏的代碼以及咱們實現的過程遇到數據改變不能刷新問題。

當我嘗試單方面的進行myUser對象數據更改的時候界面上的數據並不能自動刷新,而後我經過setUser再次設置就能夠刷新了,這簡直是煩惱啊!

帶着這個問題咱們來進一步的學習Data Binding Library。


解決問題

數據刷新自動同步如何完成呢?

解決數據同步其實谷歌已經想到了,在這裏提供了兩個解決辦法。

一、讓實體類繼承BaseObservable類

public class User extends BaseObservable{
 
    public String name;
 
    public int age;
 
    public User(String name,int age){
        this.name = name;
        this.age = age;
    }
 
    @Bindable
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
        notifyPropertyChanged(BR.user);
    }
 
    @Bindable
 
    public int getAge() {
        return age;
    }
 
    public void setAge(int age) {
        this.age = age;
        notifyPropertyChanged(BR.user);
    }
 
}

說明:

一、首先繼承BaseObservable類

二、給成員變量的get方法添加@Bindable註解

三、在成員變量的set方法的最後調用方法notifyPropertyChanged,其中裏面的參數是在BR類中記錄的變量,那些變量就是咱們在XML中聲明的那些啦,相似於安卓資源管理的R.java文件,不過這裏管理的是佈局XML的變量,是自動生成的。

在這裏我又有問題要問了,以前個人實體類這麼簡約,如今變這麼長,感受不爽!

那麼有沒有簡約版的呢,由於我很懶不想弄這麼多代碼?


二、使用Observable數據類型

這是一個簡約的方法,谷歌爲咱們提供了基於經常使用數據類型的Observable類型,就是咱們熟悉的數據類型前面加上Observable組成。

例如:

Int類型對應ObservableInt

Boolean類型對應ObservableBoolean

其餘基本類型相似以上寫法。

而String類型對應的是ObservableField<String>,ObservableField是一個泛型

咱們能夠看看他的源碼

而後再看看ObservableInt的源碼

其餘類型的源碼基本相似。這樣看來其實ObservableField除了能夠存放對象還能夠代替其餘全部基本類型來使用。

public class User {
 
    public ObservableField<String> name = new ObservableField<>();
 
    public ObservableInt age = new ObservableInt();
 
    public User(String name,int age){
        this.name.set(name);
        this.age.set(age);
    }
    
}

以上就是進過改造的實體類。

使用Observable數據類型以後數據是經過get,set方法來獲取和改變的。

在XML佈局中使用時跟原來的數據相似同樣。

public class MainActivity extends AppCompatActivity {

    private User myUser;
    private ActivityMainBinding myBinding;

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

        myBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        myUser = new User("年齡",4);
        myBinding.setUser(myUser);
        myBinding.setButtonname("年齡+1");
        myBinding.ageButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                myUser.age.set(myUser.age.get()+1);
            }
        });
    }

}
相關文章
相關標籤/搜索