DataBinding學(xué)習(xí)筆記(一)

引入DataBinding

要在當(dāng)前module的build.gradle文件中添加如下代碼

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

快速使用

第一步 :創(chuàng)建對(duì)象

一個(gè)普通的java對(duì)象即可

public class User {
    public String name;
    public String phone;
}

第二步 :修改布局

  1. 規(guī)范布局:在布局文件最外層添加一個(gè) layout 的根標(biāo)簽
  2. 引入數(shù)據(jù):在 layout 標(biāo)簽下萨咕,添加 data 標(biāo)簽
  3. 聲明對(duì)象:在 data 標(biāo)簽中添加 variable 的標(biāo)簽所坯,其中 name 表示對(duì)象名蒂窒,type 表示類名(包含包名)
  4. 關(guān)聯(lián)屬性:通過表達(dá)式 “@{}” 獲取對(duì)象的屬性,并將他們綁定到控件中
<?xml version="1.0" encoding="utf-8"?>
<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    
    <data>
        <variable name="user" type="cn.com.ursus.User"/>
    </data>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.name}"/>
    </RelativeLayout>
</layout>

注意事項(xiàng)

  1. 當(dāng) User 中的有公有屬性 name 時(shí)祟身,@{user.name} 相當(dāng)于 user.name
    當(dāng) User 中的無公有屬性 name 時(shí)肋坚,@{user.name} 相當(dāng)于 user.getName()

  2. android.text 綁定屬性的時(shí)候泵喘,注意轉(zhuǎn)成字符串拉队,如果是整型,會(huì)被當(dāng)成資源id處理握牧,可以參考下面的代碼(字符串用雙引號(hào) " " 原先外面那層雙引號(hào)轉(zhuǎn)成單引號(hào)' '

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text='@{student.age + ""}'/>

第三步 :綁定對(duì)象

  1. ActivityonCreate 方法中容诬,用 DataBindingUtil.setContentView 來替換原來的 setContentView ,得到一個(gè)名為 ActivityMainBinding 對(duì)象。( ActivityMainBinding 對(duì)象是根據(jù)布
    局文件自動(dòng)生成的沿腰,名稱來自于布局文件的名稱配合上駝峰規(guī)則览徒。)
  2. 通過剛才生成的 ActivityMainBinding 將和布局綁定的對(duì)象設(shè)置進(jìn)去
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
    User user = new User();
    user.name = "luffy";
    user.phone = "130****5678";
    binding.setUser(user);
}

這樣一個(gè)最基本的數(shù)據(jù)綁定就完成了。

Observable

綁定完之后颂龙,肯定希望的是 User 對(duì)象中的屬性值改變之后习蓬,綁定的控件也跟著自動(dòng)刷新,然而并沒有厘托,于是乎友雳,需要對(duì) User 對(duì)象進(jìn)行如下改造。

public class User extends BaseObservable{

    private String name;
    private String phone;

    @Bindable
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        notifyPropertyChanged(BR.name);
    }
    
    @Bindable
    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
        notifyPropertyChanged(BR.phone);
    }
}

注解 @Bindable 修飾 getName 方法可在 BR 類中自動(dòng)生成一個(gè)對(duì)應(yīng)屬性 name 的整型常量 BR.name铅匹。 使用 notifyPropertyChanged 方法即可刷新綁定改屬性的控件押赊。至于 BR 是什么,可以類比為 Android 中的 R

如果一個(gè)類中只有個(gè)別屬性別綁定到ui包斑,需要即使刷新流礁,而整個(gè)類又不想繼承
BaseObservable ,可以使用 ObservableField , 具體可以參考下面的代碼

public class Student {
    public final ObservableField<String> name = new ObservableField<>();
    public final ObservableField<String> grade = new ObservableField<>();
    public final ObservableInt age = new ObservableInt();
}

...

final Student student = new Student();
student.name.set("Ace");
student.grade.set("grade2");
student.age.set(1);
binding.setStudent(student);

表達(dá)式和事件

前面提過為了避免 android:text 將整型識(shí)別為資源文件罗丰,需要將整型轉(zhuǎn)成字符串神帅。

android:text='@{student.age + ""}'

由此可見在 @{} 中進(jìn)行一些簡(jiǎn)單的表達(dá)式操作。

三目運(yùn)算符 ?:

android:text="@{ user.phone != null ? user.phone : @string/no_phone}"

Null Coalescing Operator ??

這個(gè)不是 java 代碼的語法萌抵,Databinding 自定義的找御,類似于三目運(yùn)算符特殊情況的一種簡(jiǎn)易寫法

android:text="@{ user.phone ?? @string/no_phone}"

這和上面那種寫法是等價(jià)的

使用靜態(tài)屬性和靜態(tài)方法

上面代三目運(yùn)算符的例子元镀,如果我們要控制某個(gè)控件的顯示與否可以這么寫

android:visibility="@{ user.phone != null ? View.GONE : View.VISIBLE}"

這里不可以使用 gonevisible , 必須使用 View.GONEView.VISIBLE
可是這個(gè) View 是哪里來的? 我們可以在 data 標(biāo)簽中 import 進(jìn)來

<data>
    <import type="android.view.View"/>
    <import type="android.text.TextUtils"/>
</data>

import 進(jìn)來之后霎桅,我們就可以也只能使用其中的靜態(tài)屬性靜態(tài)方法

android:visibility="@{TextUtils.isEmpty(user.phone) ? View.GONE : View.VISIBLE}

注意:
如果兩個(gè) import 進(jìn)來的兩個(gè)類栖疑,類名相同,我們可以給他們?cè)O(shè)置別名

<import alias="MainActivityPresenter"
        type="cn.com.ursus.PermissionUtils"/>
<import alias="ActivityPresenter"
        type="cn.com.ursus.presenter.PermissionUtils"/>

資源文件

上面的幾個(gè)例子中在 @{} 中用到了 @string 資源文件滔驶,那么可以使用帶占位符的 @string 嗎遇革?當(dāng)然可以

<string name="welcome_name">Welcome,%s</string>
...
android:text="@{@string/welcome_name(user.name)}"

當(dāng)然除了 @string@dimen揭糕、@color 等資源文件也肯定是支持的

事件

我們可以在 @{} 中可以用表達(dá)式來響應(yīng)事件,比如最常用的 onClick,我們可以之間在之前的 User 類中編寫相應(yīng)的方法來響應(yīng)萝快,不過此處我重新創(chuàng)建一個(gè)類專門處理響應(yīng)事件。

class Presenter{
    public void clickUserName(View v){...}
    public void userNameChanged(CharSequence s, int start, int before, int count) {...}
}
...
android:onClick="@{presenter.clickUserName}"
android:onTextChanged="@{presenter.userNameChanged}"

在 Databinding 中只需要響應(yīng) onTextChanged ,無需理會(huì) beforeTextChanged afterTextChanged 著角,然而如果在代碼中實(shí)現(xiàn) onTextChanged 我們一般都會(huì)采用如下的方式揪漩,就會(huì)顯得有些臃腫。

tvName.addTextChangedListener(new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {

    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {

    }

    @Override
    public void afterTextChanged(Editable s) {

    }
});

我們自定義的響應(yīng)方法必須和常規(guī)監(jiān)聽方法保持一致的參數(shù)嗎雇寇?答案是否定的氢拥,我們可以自己定義響應(yīng)方法的參數(shù)蚌铜,不過表達(dá)式和先前略有不同锨侯,類似lambda

public void clickUserName(View v,String username){
    ...
}

...
android:onClick="@{(v)->presenter.clickUserName(v,user.name)}

還有一些表達(dá)式就不一一列舉了,下面是從官方Data Binding Guide上復(fù)制下來的目前 @{} 支持的表達(dá)式

  • Mathematical + - / * %
  • String concatenation +
  • Logical && ||
  • Binary & | ^
  • Unary + - ! ~
  • Shift >> >>> <<
  • Comparison == > < >= <=
  • instanceof
  • Grouping ()
  • Literals - character, String, numeric,null
  • Cast
  • Method calls
  • Field access
  • Array access []
  • Ternary operator ?:
  • Null Coalescing Operator ??

自定義屬性

自動(dòng)屬性

我們現(xiàn)在自定義了一個(gè)控件冬殃,其中有一個(gè)如下的 setPhoneNumber 方法

public class MyTextView extends TextView {
    ...
    public void setPhoneNumber(String phone) {
      if (!isPhoneNumber(phone)) {
         throw new IllegalArgumentException("手機(jī)號(hào)格式不正確");
      }
      String show = phone.substring(0, phone.length() - (phone.substring(3)).length())
              + "****"
              + phone.substring(7);
      setText(show);
    }
    ...
}

神奇的一幕發(fā)生了 囚痴,我們可以直接在布局文件中使用 phoneNumber 的布局屬性,雖然 MyTextView 中并沒有該屬性

<cn.com.ursus.view.MyTextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:phoneNumber="@{user.phone}"/>

自定義屬性

現(xiàn)在有個(gè)需求审葬,項(xiàng)目用的 Picasso 圖片框架深滚,我們需要在ImageView中自定義一個(gè)布局屬性,使得我們可以給該屬性設(shè)置一個(gè)網(wǎng)絡(luò)url時(shí)涣觉,自動(dòng)使用 Picasso 圖片框架來加載網(wǎng)絡(luò)圖片痴荐,該如何做?我們只需寫一個(gè)靜態(tài)方法官册,給他打上一個(gè) @BindingAdapter

@BindingAdapter({"image_url"})
public static void setImageUrl(ImageView view, String url){
   Picasso.with(MainApplication.getContext())
            .load(url)
            .placeholder(R.mipmap.ic_launcher)
            .into(view);
}

然后就可以在布局中使用該屬性了

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:image_url="@{user.icon}"/>

那么這個(gè) setImageUrl 方法該放在哪個(gè)類里呢生兆?需要將那個(gè)類導(dǎo)入布局么?
其實(shí) setImageUrl 方法可以放在任意類里面膝宁,而且不需要導(dǎo)入布局中鸦难,不過同一個(gè)控件的自定義屬性一般放在一起管理。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末员淫,一起剝皮案震驚了整個(gè)濱河市合蔽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌介返,老刑警劉巖拴事,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件沃斤,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡刃宵,警方通過查閱死者的電腦和手機(jī)轰枝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來组去,“玉大人鞍陨,你說我怎么就攤上這事〈勇。” “怎么了诚撵?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)键闺。 經(jīng)常有香客問我寿烟,道長(zhǎng),這世上最難降的妖魔是什么辛燥? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任筛武,我火速辦了婚禮,結(jié)果婚禮上挎塌,老公的妹妹穿的比我還像新娘徘六。我一直安慰自己,他們只是感情好榴都,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布待锈。 她就那樣靜靜地躺著,像睡著了一般嘴高。 火紅的嫁衣襯著肌膚如雪竿音。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天拴驮,我揣著相機(jī)與錄音春瞬,去河邊找鬼。 笑死套啤,一個(gè)胖子當(dāng)著我的面吹牛宽气,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播纲岭,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼抹竹,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了止潮?” 一聲冷哼從身側(cè)響起窃判,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎喇闸,沒想到半個(gè)月后袄琳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體询件,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鸣奔,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年绘盟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了沪蓬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片弄喘。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蒙具,靈堂內(nèi)的尸體忽然破棺而出冒萄,到底是詐尸還是另有隱情池摧,我是刑警寧澤片效,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布红伦,位于F島的核電站,受9級(jí)特大地震影響淀衣,放射性物質(zhì)發(fā)生泄漏昙读。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一膨桥、第九天 我趴在偏房一處隱蔽的房頂上張望蛮浑。 院中可真熱鬧,春花似錦只嚣、人聲如沸沮稚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽壮虫。三九已至澳厢,卻和暖如春环础,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背剩拢。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工线得, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人徐伐。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓贯钩,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親办素。 傳聞我的和親對(duì)象是個(gè)殘疾皇子角雷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)性穿,斷路器勺三,智...
    卡卡羅2017閱讀 134,659評(píng)論 18 139
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,162評(píng)論 25 707
  • DataBinding整體使用流程 開發(fā)階段 UserModel.java activity_main.xml 在...
    listen2code閱讀 3,142評(píng)論 7 15
  • 我是在第三次被楊鵬拒絕的時(shí)候,開始懷疑起了他的性取向需曾。 “都說女追男吗坚,隔層紗祈远,可我和楊鵬中間隔的哪是什么紗,這特么...
    岸上行走的魚閱讀 5,593評(píng)論 168 262
  • 無戒365訓(xùn)練營(yíng)極限挑戰(zhàn)第13天 人物的巨大轉(zhuǎn)變對(duì)于故事是否好看的重要性在于商源,它讓一個(gè)角色擁有了兩面或者多面的形象...
    揚(yáng)菁閱讀 686評(píng)論 0 1