前言
用DataBinding差不多現(xiàn)經(jīng)手了三個項目,也用它開發(fā)了一年左右,對它的特性以及使用方面有了一些自己的理解,這里面可以和大家一起分享一下,詳解DataBinding文檔中的知識點,以及工作中可能遇到的一些問題,我每講一部分都是寫一個相應(yīng)的demo以供參考.
DataBinding是什么?
官網(wǎng)文檔地址:https://developer.android.com/topic/libraries/data-binding/index.html
翻譯文檔:自己谷歌搜索,網(wǎng)上已經(jīng)有,這里就不再翻譯
官方文檔的原話是:Data Binding Library to write declarative layouts and minimize the glue code necessary to bind your application logic and layouts,The Data Binding Library offers both flexibility and broad compatibility — it's a support library,大致的意思就是DataBinding是一個通過膠水代碼寫聲明布局文件并減少綁定應(yīng)用程序邏輯的一個具有兼容和靈活性的一個支持庫.看了之后還是一臉懵逼,不要緊,學(xué)知識嘛,慢慢來.
如何集成
集成很簡單,在你app module的Gradle下面添加的代碼:
android {
....
dataBinding {
enabled = true
}
}
提醒:現(xiàn)在建議大家的AS更新到最新,目前最新穩(wěn)定版式2.3.3.另外,你們公司如果接受了DataBinding這個還算有點新的東西,那么我建議大家使用JDK1.8,具體的詳細介紹,請看官網(wǎng)上面的介紹,https://developer.android.com/guide/platform/j8-jack.html.
AS2.1以上才支持jack,如果你得AS版本比較低的話,可以使用兼容庫Retrolambda.目前的穩(wěn)定版而言,暫時不能使用instant run.
集成如下:
android {
defaultConfig {
....
jackOptions {
enabled true
}
}
....
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
note:如果你用的AS3.0的話,就可以不通過jack進行編譯,而且可以使用instant run,還加快的編譯速度.具體的介紹:
http://developers.googleblog.cn/2017/05/android-studio-30-canary-1.html
如何使用
在工作中,我們經(jīng)常遇到請求到一個對象,然后對象的信息需要在xml中展示的情況,用它怎么做到嗎?比普通的做法有什么優(yōu)勢?
- 假如我們請求到的是一個學(xué)生的實體類,那么我們先創(chuàng)建一個學(xué)生類:
public class Student {
private String name;
private int age;
private String headerImg;
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;
}
public String getHeaderImg() {
return headerImg;
}
public void setHeaderImg(String headerImg) {
this.headerImg = headerImg;
}
}
- 這個學(xué)生類包括姓名,年齡和頭像的url,現(xiàn)在我們模擬一下網(wǎng)絡(luò)請求:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo1);
initData();
}
private void initData() {
//模擬網(wǎng)絡(luò)請求部分,假如請求到了一個學(xué)生實體
Student student = new Student();
student.setAge(25);
student.setName("李寧");
student.setHeaderImg("http://i2.muimg.com/567571/b528af67d68f7597.png");
}
- 下面正常的做法就是拿到xml里面的空間,然后一個一個賦值上去,是不是感覺這樣做不僅要findViewById,還要拿到各種控件進行一系列的賦值挺麻煩的,這時候DataBinding的作用就展示出來了,數(shù)據(jù)綁定,就是要把數(shù)據(jù)直接綁定到xml上面.下面看我華麗的操作:
XMl中:
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
<variable
name="student"
type="com.DataBinding.lsh.databindingdemo.Student" />
</data>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.DataBinding.lsh.databindingdemo.Demo1.Demo1Activity">
</LinearLayout>
</layout>
跟布局的標(biāo)簽換了,換成了layout,其次多了data標(biāo)簽,下面有個一個varible標(biāo)簽,它的作用就是用來聲明xml中綁定的變量,這里面的Type一定要寫引用的全路徑,不過好在現(xiàn)在都可以智能提示,打上一個Student,選擇正確的一個,下面我們就要在xml的控件中綁定我們聲明變量的字段,你可能會說,咦?student只是聲明了,不是還沒有給進行賦值嗎?現(xiàn)在綁定上去不會報錯嗎?這個不用擔(dān)心,它有一系列的默認值.一陣亂敲之后:
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
<variable
name="student"
type="com.DataBinding.lsh.databindingdemo.Student" />
</data>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:fresco="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.DataBinding.lsh.databindingdemo.Demo1.Demo1Activity">
<com.facebook.drawee.view.SimpleDraweeView
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_gravity="center"
fresco:actualImageScaleType="fitXY"
fresco:placeholderImage="@mipmap/ic_launcher"
fresco:placeholderImageScaleType="centerCrop"
fresco:roundAsCircle="true" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="李寧"
android:textSize="24sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="25"
android:textSize="24sp" />
</LinearLayout>
</layout>
我這里面用的加載圖片的工具是fresco,它很強大,尤其在內(nèi)存方面,而且還有一集成了一些常用的功能,比如圓形頭像,圓角頭像,gif播放,等常用的一些功能.
接下來開始綁定:
先綁定TextView的屬性,寫法如上述圖片,控件中自帶的這些屬性一般可以直接綁定,如果想綁定一些沒有的屬性,就需要自己去指定,下面綁定圖片地址展示圖片的時候會用到.我們xml中除了圖片,文本就綁定好了,那么activity要怎么操作呢?
在Activity中:
- DataBinding通過DataBindingUtil來進行綁定視圖,常用的有兩個方法,一個是setContentView方法,一個是bind方法,前者一般用著Activity加載視圖,后者就是Fragment等.
- 一個xml對應(yīng)一個Binding的java文件,這個文件是自動生成的,如果提示不出來這個類,重啟As,如果還是不行,把項目中的build文件夾刪除了,重新編譯,滿滿的都是經(jīng)驗啊.這個類在build下面是可以找到的,路徑如下圖:
- 最后我們對xml中的變量進行賦值
異常
我們愉快的編譯運行,忽然閃退了,看異常:
點進去:
mboundView2就是我們設(shè)置年齡文本,后面的studentAge就是我們設(shè)置的年齡,這地方怎么會報錯呢?
想一想,原來是我們student的age是int類型的,但是text屬性不能直接設(shè)置int類型,那怎么辦?
在string.xml中
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@{@string/intToString(student.age)}"
android:textSize="24sp" />
在activity_demo1.xml中:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@{@string/intToString(student.age)}"
android:textSize="24sp" />
其他的類型的轉(zhuǎn)化就可以參照這個去改.
綁定圖片
public class ViewBindAdapter {
@BindingAdapter({"bind:url"})
public static void setImgUrl(SimpleDraweeView imageView, String uri) {
if (!TextUtils.isEmpty(uri)) {
imageView.setImageURI(Uri.parse(uri));
}
}
}
xml中:
<com.facebook.drawee.view.SimpleDraweeView
app:url="@{student.headerImg}"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_gravity="center"
fresco:actualImageScaleType="fitXY"
fresco:placeholderImage="@mipmap/zhanwei"
fresco:placeholderImageScaleType="centerCrop"
fresco:roundAsCircle="true" />
我們新建一個類,專門存放綁定的自定義屬性,@BindingAdapter({"bind:url"})這句主要是聲明xml中寫的自定義的屬性,可以連續(xù)寫多個,比如這種:
@BindingAdapter(value = {"uri", "placeholderImageRes", "request_width","request_height"}, requireAll = false)
public static void loadImage(final ImageView imageView, String uri,
@DrawableRes int placeholderImageRes,
int width, int height){
}
requireAll = false的意思是不用寫全所有參數(shù),方法的第一個參數(shù)是控件的本身,就是這么簡單,這樣就可以綁定成功了.
note:注意app:url="@{student.headerImg}"這個沒有智能提示,代碼顏色也沒有改變,都是正常的,只要寫對就行.
最新來一張圖:
到這里,這些基本的操作就完成了,你已經(jīng)對databinding有了一個大體的認識,接下來的幾篇,將會更加深入的介紹它的使用方法和底層的原理.
demo地址:https://github.com/adonis-lsh/DataBindingDemo