Android Data-Binding簡(jiǎn)記

從我的CSDN博客http://blog.csdn.net/dahaohan 遷移的第一篇博文祥款。

What's Data-Binding孙蒙?

看過(guò)我之前轉(zhuǎn)發(fā)的博文Android App的設(shè)計(jì)架構(gòu):MVC,MVP,MVVM經(jīng)驗(yàn)談
可以了解到移動(dòng)端App開(kāi)發(fā)架構(gòu)從傳統(tǒng)MVC-->MVP-->MVVM的一些進(jìn)展和演化,而目前發(fā)展成的MVVM架構(gòu)則需要使用Data-Binding機(jī)制來(lái)完成View和ViewModel之間的通信。
2015年google I/0開(kāi)發(fā)者大會(huì)發(fā)布的Data-binding庫(kù)邦危,使得開(kāi)發(fā)者可以更加簡(jiǎn)潔優(yōu)雅的編寫(xiě)代碼實(shí)現(xiàn)復(fù)雜的業(yè)務(wù)邏輯脚翘,而不必去關(guān)注數(shù)據(jù)變更后UI View的更新問(wèn)題耻姥。View的變化會(huì)直接影響ViewModel秧了,ViewModel的變化或者內(nèi)容也會(huì)直接體現(xiàn)在View上翩瓜,這就是Data Binding Library默默幫您完成的工作受扳。
Android官方Data Binding介紹:https://developer.android.com/topic/libraries/data-binding/index.html

Data Binding Requirements

The Data Binding Library offers both flexibility and broad compatibility — it's a support library, so you can use it with all Android platform versions back to Android 2.1 (API level 7+).
To use data binding, Android Plugin for Gradle 1.5.0-alpha1 or higher is required.
Also, make sure you are using a compatible version of Android Studio. Android Studio 1.3 and later provides support for data binding.

Data binding 是一個(gè)類似support-v4/v7的支持庫(kù),API 7+都可以使用兔跌;
Android Studio1.3+
Android Gradle插件 1.5.0 +

How To Use Data Binding勘高?

要使用Data binding功能需要在你app module 的build.gradle中開(kāi)啟。

android {
    ....
    dataBinding {
        enabled = true
    }
}

<h3>Data binding Layout

使用Data binding核心是將viewModel數(shù)據(jù)嵌入到布局layout xml文件坟桅,故而layout xml文件與之前的純view布局文件的構(gòu)成略有不同华望。

//以下為官方給出的最簡(jiǎn)單的一個(gè)示例:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable
            name="user"
            type="test.example.com.databindingtest.User">
        </variable>
    </data>

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:id="@+id/firstname_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.firstName}"/>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.lastName}"/>
    </LinearLayout>

</layout>

public class User {
   public final String firstName;
   public final String lastName;
   public User(String firstName, String lastName) {
       this.firstName = firstName;
       this.lastName = lastName;
   }
}

Data binding的布局文件的根節(jié)點(diǎn)為layout標(biāo)簽,由一個(gè)數(shù)據(jù)data標(biāo)簽以及一個(gè)根視圖標(biāo)簽構(gòu)成仅乓。
data標(biāo)簽聲明了該View使用的數(shù)據(jù)模型viewModel為變量名為user的User類對(duì)象立美,然后在Root View標(biāo)簽下通過(guò)
@{“變量名" + "." + ”屬性名/函數(shù)名“}來(lái)給指定的view設(shè)置值。

PS:

//對(duì)于User類的另一種寫(xiě)法
public class User {
   private final String firstName;
   private final String lastName;
   public User(String firstName, String lastName) {
       this.firstName = firstName;
       this.lastName = lastName;
   }
   public String getFirstName() {
       return this.firstName;
   }
   public String getLastName() {
       return this.lastName;
   }
}

關(guān)于Data binding框架識(shí)別語(yǔ)句 @{user.firstName} 的一個(gè)機(jī)制是對(duì)于第一種寫(xiě)法訪問(wèn)User類的 firstName屬性方灾,而第二種寫(xiě)法則是訪問(wèn)User類的getFirstName()方法建蹄,或者也有可能訪問(wèn)firstName()方法如果存在的話。

<h3>Binding Data

編寫(xiě)完成data binding layout之后裕偿,類似IDE自動(dòng)編譯資源文件產(chǎn)生資源ID R文件洞慎,默認(rèn)將以layout xml文件的名字為基礎(chǔ)生成一個(gè)繼承自ViewDataBinding的類,此例xml文件為activity_main.xml故而生成ActivityMainBinding.java
生成的ViewDataBinding類默認(rèn)命名規(guī)則為嘿棘,布局xml文件名去掉"_"以駝峰式寫(xiě)法+“Binding”劲腿,當(dāng)然也支持自定義命名,后續(xù)提及

對(duì)于Android Studio IDE可以在
app/build/intermediates/classes/debug/+"對(duì)應(yīng)包目錄"+databinding文件夾下查看該生成的ViewDataBinding類


這里寫(xiě)圖片描述

PS:注意這里生成的ActivityMainBinding內(nèi)的以下幾個(gè)屬性和函數(shù)

public class ActivityMainBinding extends android.databinding.ViewDataBinding  {
    ..........
    .....
    // views
    //在layout xml內(nèi)定義了id的 android:id="@+id/firstname_text"
    //Viewdatabinding將會(huì)以駝峰命名生成對(duì)應(yīng):
    //public final android.widget.TextView firstnameText;
    //通過(guò)獲得的binding類以及view的id名稱可以直接獲取該view的引用鸟妙,而不需要再findViewById
    public final android.widget.TextView firstnameText;

    //未設(shè)置id的view則只會(huì)定義為private焦人,外部將不可訪問(wèn)
    private final android.widget.LinearLayout mboundView0;
    private final android.widget.TextView mboundView2;

    //layout內(nèi)聲明的變量,對(duì)應(yīng)成員變量以及默認(rèn)以駝峰命名生成set/get函數(shù)setUser
    //用于給dataBinding設(shè)置數(shù)據(jù)viewModel
    // variables
    private test.example.com.databindingtest.User mUser;
    ........
    public void setUser(test.example.com.databindingtest.User user) {
        this.mUser = user;
        synchronized(this) {
            mDirtyFlags |= 0x1L;
        }
        notifyPropertyChanged(BR.user);
        super.requestRebind();
    }
    public test.example.com.databindingtest.User getUser() {
        return mUser;
    }
    ........
    ..................
  }

略微查看默認(rèn)生成的ActivityMainBinding類重父,可以看出binding類就是管理并維護(hù)View與View Model的關(guān)系的核心花椭。包括給將user數(shù)據(jù)對(duì)應(yīng)值賦值給對(duì)應(yīng)的view視圖;當(dāng)user內(nèi)值變化時(shí)更新視圖房午;視圖交互事件調(diào)用viewmodel的業(yè)務(wù)邏輯等矿辽。

ViewDataBinding相當(dāng)于一個(gè)聯(lián)系對(duì)應(yīng)layout中View與對(duì)應(yīng)ViewModel(data標(biāo)簽下的數(shù)據(jù))的框架,我們使用時(shí)需要將對(duì)應(yīng)的View和ViewModel實(shí)例對(duì)象傳遞給該ViewDataBinding框架,Data Binding庫(kù)已經(jīng)提供了多種方法來(lái)給實(shí)現(xiàn):

@Override
protected void onCreate(Bundle savedInstanceState) {

   //獲取ViewDataBinding實(shí)例對(duì)象的同時(shí)已經(jīng)通過(guò)傳遞對(duì)應(yīng)的View對(duì)象或者layout文件參數(shù)袋倔,
   //將對(duì)應(yīng)的View實(shí)例對(duì)象傳遞給該ViewDataBinding框架
   
   //Activity最常用的取代之前的setContentView方法
   MainActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity);
   //可直接通過(guò)id名稱訪問(wèn)對(duì)應(yīng)View變量
   dataBinding.firstnameText.setText("hello");
   
   //使用默認(rèn)生成的ActivityMainBinding直接bind對(duì)應(yīng)View
   dataBinding = ActivityMainBinding.bind(viewRoot);
   //或者如下
   dataBinding = ActivityMainBinding.inflate(getLayoutInflater());
   
   ViewDataBinding binding = DataBindingUtil.inflate(LayoutInflater, layoutId,
    parent, attachToParent);
    
   //給DataBinding框架設(shè)置viewModel數(shù)據(jù)源User
   User user = new User("Test", "User");
   //set方法根據(jù)layout中聲明的數(shù)據(jù)類型自動(dòng)生成
   binding.setUser(user);
}

上述步驟完成運(yùn)行即可發(fā)現(xiàn)雕蔽,user各屬性數(shù)據(jù)自動(dòng)綁定到了各自的View上,但是這只體現(xiàn)了dataBinding單方面從ViewModel到View的數(shù)據(jù)綁定宾娜;如何實(shí)現(xiàn)user數(shù)據(jù)更新然后DataBinding自動(dòng)更新UiView批狐? View的交互事件如何綁定到ViewModel的業(yè)務(wù)邏輯?

Data Binding View Event Handling##

類似data binding提供的View的數(shù)據(jù)綁定前塔,在layout的view標(biāo)簽內(nèi)同樣允許使用表達(dá)式直接引用相應(yīng)的函數(shù)處理分發(fā)的事件贾陷。使用函數(shù)引用的View 屬性由對(duì)應(yīng)的事件listener的函數(shù)方法決定:

    //View一般有View.OnLongClickListener/ View.OnClickListener
    //對(duì)應(yīng)的兩個(gè)方法為onLongClick/onClick故而data binding在view標(biāo)簽下有如下屬性:
    android:onClick="@{user.onLastNameClick}"
    android:onLongClick="@{user.onLastNameLongClick}"

若在User類加入以下函數(shù),則在View內(nèi)完整引用監(jiān)聽(tīng)click事件寫(xiě)法如下:

public class User {
    ....
    ........
    public void onLastNameClick(View v){
        Log.d("Test"," onLastNameClick ");
    }
    public boolean onLastNameLongClick(View v){
        Log.d("Test"," onLastNameLongClick ");
        return false;
    }
    ....
    .......
}

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="user"
            type="test.example.com.databindingtest.User">
        </variable>
    </data>
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:id="@+id/firstname_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.firstName}"/>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.lastName}"
            android:onClick="@{user.onLastNameClick}"
            android:onLongClick="@{user.onLastNameClick}"/>
    </LinearLayout>
</layout>

進(jìn)行編譯后運(yùn)行即可發(fā)現(xiàn)點(diǎn)擊交互事件可以順利觸發(fā)和處理嘱根。

Android官方對(duì)于View標(biāo)簽引用的事件處理函數(shù)的要求說(shuō)明:

In your expressions, you can reference methods that conform to the signature of the listener method. When an expression evaluates to a method reference, Data Binding wraps the method reference and owner object in a listener, and sets that listener on the target view. If the expression evaluates to null, Data Binding does not create a listener and sets a null listener instead.

官方說(shuō)明View處理事件引用的方法的簽名要與對(duì)應(yīng)的clickListener的方法簽名相符髓废,而方法的簽名側(cè)重的是方法名和方法參數(shù)的順序、類型该抒、個(gè)數(shù)慌洪;這里測(cè)試之后其實(shí)需要的是與對(duì)應(yīng)的clickListener的方法的參數(shù)以及返回值一致。

編譯期間將對(duì)View#onClick attribute的表達(dá)式引用的方法進(jìn)行合法性檢查凑保,若是方法參數(shù)/返回值對(duì)應(yīng)不上冈爹,則會(huì)出現(xiàn)編譯錯(cuò)誤:

Error:(26, 36) Listener class android.view.View.OnLongClickListener with method onLongClick did not match signature of any method user.onLastNameLongClick 

若編譯正確,實(shí)質(zhì)其實(shí)還是將該方法包裝進(jìn)一個(gè)對(duì)應(yīng)的listener然后給view設(shè)置對(duì)應(yīng)監(jiān)聽(tīng)接口欧引。

Data Binding listening data/properties changes

Data binding真正的好處提現(xiàn)在data(user)數(shù)據(jù)變化時(shí)频伤,能夠自動(dòng)更新對(duì)應(yīng)的UI顯示,如何使用這個(gè)核心功能呢芝此?
<h3>Observable 對(duì)象

private static class User extends BaseObservable {
   private String firstName;
   private String lastName;
    
   //Bindable注解告訴data binding框架需要偵聽(tīng)該值的變化
   //編譯期間生成的類似R文件的一個(gè)BR文件將會(huì)有該屬性的一個(gè)public資源Id
   @Bindable
   public String getFirstName() {
       return this.firstName;
   }
   @Bindable
   public String getLastName() {
       return this.lastName;
   }
   public void setFirstName(String firstName) {
       this.firstName = firstName;
       //通過(guò)對(duì)應(yīng)屬性的資源ID告訴data binding框架該屬性發(fā)生變化需要更新ui什么的
       notifyPropertyChanged(BR.firstName);
   }
   public void setLastName(String lastName) {
       this.lastName = lastName;
       notifyPropertyChanged(BR.lastName);
   }
}

限定了修改屬性數(shù)據(jù)的方法在對(duì)應(yīng)的set方法內(nèi)憋肖,所以在set方法更新屬性后通知data binding框架屬性的更新即可。

<h3>ObservableFields

其實(shí)與上述的BaseObservable對(duì)象是類似的原理婚苹,只是將整個(gè)類的范圍縮小到個(gè)別需要偵聽(tīng)的屬性上岸更,提供了ObservableBoolean, ObservableByte, ObservableChar, ObservableShort, ObservableInt, ObservableLong, ObservableFloat, ObservableDouble, and ObservableParcelable.

private static class User {
   public final ObservableField<String> firstName =
       new ObservableField<>();
   public final ObservableField<String> lastName =
       new ObservableField<>();
   public final ObservableInt age = new ObservableInt();
}

user.firstName.set("Google");
int age = user.age.get();

事實(shí)上每一個(gè)ObservableFields都繼承自BaseObservable包含了單獨(dú)一個(gè)屬性值,內(nèi)部默認(rèn)封裝了set/get方法膊升,將上述BaseObservable的方法封裝好了怎炊,也是在set方法之后通知data-binding框架做出一些更新操作。

<h3>Observable Collections

對(duì)于一些需要使用到list/map等集合數(shù)據(jù)類型來(lái)說(shuō)有: ObservableArrayMap廓译,ObservableArrayList等

ObservableArrayMap<String, Object> user = new ObservableArrayMap<>();
user.put("firstName", "Google");
user.put("lastName", "Inc.");
user.put("age", 17);

<data>
    <import type="android.databinding.ObservableMap"/>
    <variable name="user" type="ObservableMap<String, Object>"/>
</data>
…
<TextView
   android:text='@{user["lastName"]}'
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>
<TextView
   android:text='@{String.valueOf(1 + (Integer)user["age"])}'
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

PS: Android Studio IDE目前并不能很完美的支持到data標(biāo)簽的一些變量的import或者是類型聲明评肆;但是并不會(huì)影響編譯運(yùn)行。


這里寫(xiě)圖片描述
ObservableArrayList<Object> user = new ObservableArrayList<>();
user.add("Google");
user.add("Inc.");
user.add(17);

<data>
    <import type="android.databinding.ObservableList"/>
    <variable name="user" type="ObservableList<Object>"/>
</data>
…
<TextView
   android:text="@{user[0]}"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>
<TextView
   android:text="@{String.valueOf(1 + (Integer)user[2])}"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

Some Details

關(guān)于data標(biāo)簽支持import類似java的import非区,以及其對(duì)于一些類似map/list/array等集合類型的數(shù)據(jù)的語(yǔ)法簡(jiǎn)要介紹:

//下面的 < 為符號(hào)'<'字符實(shí)體
<data>
    <import type="android.util.SparseArray"/>
    <import type="java.util.Map"/>
    <import type="java.util.List"/>
    <variable name="list" type="List<String>"/>
    <variable name="sparse" type="SparseArray<String>"/>
    <variable name="map" type="Map<String, String>"/>
    <variable name="index" type="int"/>
    <variable name="key" type="String"/>
</data>

…
android:text="@{list[index]}"
…
android:text="@{sparse[index]}"
…
android:text="@{map[key]}"

//集合類型數(shù)據(jù)都是類似數(shù)組使用的'[]'訪問(wèn)特定的數(shù)據(jù)瓜挽,對(duì)于數(shù)組[]內(nèi)是對(duì)應(yīng)的下標(biāo),對(duì)于map則是對(duì)應(yīng)的key值

PS: Map的key為一個(gè)String時(shí)院仿,可能遇到引號(hào)內(nèi)要使用引號(hào)包括字符串的沖突秸抚,這時(shí)使用:

//單引號(hào)在外包括速和,內(nèi)部使用雙引號(hào)標(biāo)示字符串
android:text='@{map["firstName"]}'
//或者外部使用雙引號(hào)歹垫,內(nèi)部用back quote反引號(hào)標(biāo)示字符串(反引號(hào)即'~'按鍵)
android:text="@{map[`firstName`}"

//或者使用"即雙引號(hào)的java字符實(shí)體來(lái)替代雙引號(hào)
android:text="@{map["firstName"]}"

About More Details

關(guān)于data binding的細(xì)節(jié)知識(shí)推薦閱讀:
官方介紹文檔:https://developer.android.com/topic/libraries/data-binding/index.html
比較全面的官方文檔的翻譯檔:http://www.reibang.com/p/b1df61a4df77
結(jié)合實(shí)例的介紹:https://github.com/LyndonChin/MasteringAndroidDataBinding

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末剥汤,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子排惨,更是在濱河造成了極大的恐慌吭敢,老刑警劉巖,帶你破解...
    沈念sama閱讀 223,126評(píng)論 6 520
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件暮芭,死亡現(xiàn)場(chǎng)離奇詭異鹿驼,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)辕宏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,421評(píng)論 3 400
  • 文/潘曉璐 我一進(jìn)店門(mén)畜晰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人瑞筐,你說(shuō)我怎么就攤上這事凄鼻。” “怎么了聚假?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,941評(píng)論 0 366
  • 文/不壞的土叔 我叫張陵块蚌,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我膘格,道長(zhǎng)峭范,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,294評(píng)論 1 300
  • 正文 為了忘掉前任瘪贱,我火速辦了婚禮纱控,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘菜秦。我一直安慰自己其徙,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,295評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布喷户。 她就那樣靜靜地躺著唾那,像睡著了一般。 火紅的嫁衣襯著肌膚如雪褪尝。 梳的紋絲不亂的頭發(fā)上闹获,一...
    開(kāi)封第一講書(shū)人閱讀 52,874評(píng)論 1 314
  • 那天,我揣著相機(jī)與錄音河哑,去河邊找鬼避诽。 笑死,一個(gè)胖子當(dāng)著我的面吹牛璃谨,可吹牛的內(nèi)容都是我干的沙庐。 我是一名探鬼主播鲤妥,決...
    沈念sama閱讀 41,285評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼拱雏!你這毒婦竟也來(lái)了棉安?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 40,249評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤铸抑,失蹤者是張志新(化名)和其女友劉穎贡耽,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體鹊汛,經(jīng)...
    沈念sama閱讀 46,760評(píng)論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蒲赂,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,840評(píng)論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了刁憋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片滥嘴。...
    茶點(diǎn)故事閱讀 40,973評(píng)論 1 354
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖至耻,靈堂內(nèi)的尸體忽然破棺而出若皱,到底是詐尸還是另有隱情,我是刑警寧澤有梆,帶...
    沈念sama閱讀 36,631評(píng)論 5 351
  • 正文 年R本政府宣布是尖,位于F島的核電站,受9級(jí)特大地震影響泥耀,放射性物質(zhì)發(fā)生泄漏饺汹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,315評(píng)論 3 336
  • 文/蒙蒙 一痰催、第九天 我趴在偏房一處隱蔽的房頂上張望兜辞。 院中可真熱鬧,春花似錦夸溶、人聲如沸逸吵。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,797評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)扫皱。三九已至,卻和暖如春捷绑,著一層夾襖步出監(jiān)牢的瞬間韩脑,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,926評(píng)論 1 275
  • 我被黑心中介騙來(lái)泰國(guó)打工粹污, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留段多,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,431評(píng)論 3 379
  • 正文 我出身青樓壮吩,卻偏偏與公主長(zhǎng)得像进苍,于是被迫代替她去往敵國(guó)和親加缘。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,982評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • 在 Android 開(kāi)發(fā)過(guò)程中觉啊,由于 Android 作為 View 描述的 xml 視圖功能較弱拣宏,開(kāi)發(fā)中很容易寫(xiě)...
    射覆閱讀 4,242評(píng)論 0 22
  • *本篇文章已授權(quán)微信公眾號(hào) guolin_blog (郭霖)獨(dú)家發(fā)布 什么是MVVM 說(shuō)到DataBinding,...
    帶心情去旅行閱讀 8,611評(píng)論 23 91
  • 前幾天在忙一些其他的東西柄延,DataBinding 這個(gè)系列的博客本應(yīng)該在五月月初就要寫(xiě)的蚀浆,結(jié)果一直拖到了現(xiàn)在缀程,罪過(guò)...
    lijiankun24閱讀 1,181評(píng)論 0 2
  • 當(dāng)你走進(jìn)這歡樂(lè)場(chǎng) 背上所有的夢(mèng)與想 各色的臉上各色的妝 沒(méi)人記得你的模樣 三巡酒過(guò)你在角落 固執(zhí)的唱著苦澀的歌 聽(tīng)...
    仰慕兒閱讀 816評(píng)論 0 1
  • 夢(mèng)想有時(shí)候是一場(chǎng)雨搜吧, 能滋潤(rùn)萬(wàn)頃良田; 夢(mèng)想有時(shí)候是一束光杨凑, 能照亮每一角落滤奈!
    有娜么點(diǎn)兒意思閱讀 174評(píng)論 0 2