DataBinding快速入門
一、DataBinding介紹
DataBinding翻譯過來就是資料繫結,把資料繫結在控制元件上。本篇講述的都是單向繫結,即資料繫結到控制元件上。現在已經支援雙向繫結,也就是說,還可以把控制元件繫結在資料上。
DataBinding可以代替findViewById,讓程式碼更簡潔,而且比註解框架(如ButterKnife)效率高。
二、DataBinding使用
2.1 準備工作
環境要求:
Gradle 外掛版本不低於 1.5.0-alpha1
Android Studio 版本要高於 1.3
在module(如:app)的build.gradle中新增dataBinding的使能開關
android {
compileSdkVersion 24
buildToolsVersion "23.0.2"
defaultConfig {
}
// add
dataBinding{
enabled true
}
然後使用Sync now同步。
2.2 快速使用
2.2.1 建立一個Bean類
建立一個User類:
public class User{ String name; String nickname; boolean isMale; int age; public User(String name, String nickname, boolean isMale, int age) { this.name = name; this.nickname = nickname; this.isMale = isMale; this.age = age; } //Getter and Setter,省略 }
2.2.2 修改xml佈局檔案
步驟:
1.在原佈局檔案外套一層layout標籤,把名稱空間移到layout標籤內
2.layout標籤內部包含資料模組和樣式模組(原佈局)
3.資料模組使用data標籤,定義變數名稱name——下面android:text屬性中呼叫的名稱,及型別type——定義變數所指的型別或類(如果是自定義類,必須給完整包名+類名)
<?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="com.zjun.databinding.demo.bean.User" /> </data> <LinearLayout android:id="@+id/activity_fast_use" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="@dimen/activity_vertical_margin" tools:context="com.zjun.databinding.demo.FastUseActivity"> <LinearLayout style="@style/StyleItemParent"> <Button android:id="@+id/btn_load" style="@style/StyleBeforeText" android:text="資料1" /> <Button android:id="@+id/btn_change" style="@style/StyleBeforeText" android:text="資料2" /> </LinearLayout> <LinearLayout style="@style/StyleItemParent"> <TextView style="@style/StyleBeforeText" android:text="姓名:" /> <TextView style="@style/StyleAfterText" android:text="@{user.name}" android:onClick="@{user.onNameClick}"/> </LinearLayout> <LinearLayout style="@style/StyleItemParent"> <TextView style="@style/StyleBeforeText" android:text="暱稱:" /> <TextView style="@style/StyleAfterText" android:text="@{user.nickname ?? user.name}" android:onLongClick="@{user.onNicknameLongClick}"/> </LinearLayout> <LinearLayout style="@style/StyleItemParent"> <TextView style="@style/StyleBeforeText" android:text="性別:" /> <TextView style="@style/StyleAfterText" android:textColor="@{user.male ? 0xFF0000FF : 0xFFFF0000}" android:text='@{user.male ? @string/male : @string/female}' /> </LinearLayout> <LinearLayout style="@style/StyleItemParent"> <TextView style="@style/StyleBeforeText" android:text="年齡:" /> <TextView style="@style/StyleAfterText" android:textColor="@{user.age < 14 || user.age > 65 ? 0xFFFF0000 : 0xFF000000}" android:text='@{String.valueOf(user.age) + " years old"}' /> </LinearLayout> </LinearLayout> </layout>
2.2.3 xml中的使用語法
上面的資料繫結中,主要是把資料顯示android:text屬性中(點選事件暫不考慮),必須注意語法:
1.每一個變數variable都是由名稱name和型別type組成。name可以在佈局檔案中使用,也可以通過Setter和Getter在程式碼中使用。type可以是基本資料型別、集合、介面卡、自定義類等,除了基本型別,其他都必須把包名寫全
2.雙引號中可以套“`”(Tab鍵上面,非單引號),單引號內可以套雙引號;
3.不能直接用boolean和int型別的值。而且int值將被當做資原始檔。因此要使用其數值,必須轉換成字串,如(boolean同理):
"@{user.age + ``}",或 "@{String.valueOf(user.age)}"
4.顏色必須使用ARGB制,指定其所有的透明度和單色值,以前的#F00和#FF0000無效,且前面不能加“#”
5."@{user.nickname ?? user.name}",代表user.nickname為null時顯示user.name,否則顯示自己。等同於"@{user.nickname == null ? user.name : user.nickname}"
6.比較運算子,必須使用轉義字元:
大於號“>”——>
小於號“<”——<
7.不能直接使用中文(MD),如:
android:text='@{user.male ? "男" : "女"}'
將報錯,得用string引用,改成:
android:text='@{user.male ? @string/male : @string/female}'
2.2.4 程式碼中修改資料
public class FastUseActivity extends AppCompatActivity {
private ActivityFastUseBinding mBinding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 換掉setContentView()
// setContentView(R.layout.activity_fast_use);
mBinding= DataBindingUtil.setContentView(this, R.layout.activity_fast_use);
}
public void onClick(View view) {
User user = new User("張君寶", "張三丰", true, 30);
mBinding.setUser(user);
}
}
其中:
ActivityFastUseBinding是由佈局檔案activity_fast_use.xml的檔名生成的。
DataBindingUtil.setContextView()生成的是抽象類ViewDataBinding,但不能用作定義mBinding,因為設定資料時,需要用到其實現類的方法,如setUser()。
執行結果:
![](https://img-blog.csdn.net/20161107234737092)
2.3 監聽事件
可以設定控制元件的點選與長按事件。
A. 先定義監聽事件處理方法
在Bean類中新增點選事件:
public class User{
String name;
String nickname;
boolean isMale;
int age;
public void onNameClick(View view) {
Toast.makeText(view.getContext(), name + " is Clicked", Toast.LENGTH_SHORT).show();
}
public boolean onNicknameLongClick(View view) {
Toast.makeText(view.getContext(), nickname + " is long Clicked", Toast.LENGTH_SHORT).show();
return true;
}
B. 在xml中使用
<TextView
android:text="@{user.name}"
android:onClick="@{user.onNameClick}"
/>
<TextView
android:text="@{user.nickname ?? user.name}"
android:onLongClick="@{user.onNicknameLongClick}"
/>
注意:
1.自定義監聽事件方法的引數、返回值必須與原監聽事件裡的方法一樣。如點選事件必須與onClick(View view)一樣,引數是View,返回值是void;長按事件與onLongCLick(View view)一樣,引數是View,返回值是boolean
2.android:onLongClick會提示沒有此屬性,但只要不報錯就沒關係
2.4 include的引數傳遞
佈局檔案中,經常會用到include子佈局,那如何把父佈局中的資料傳遞給子佈局呢?方法就是通過自定義屬性。
(1)子佈局layout_include_params.xml——與之前一樣,定義資料模組,然後使用就OK:
<?xml version="1.0" encoding="utf-8"?>
<layout ...
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="user"
type="com.zjun.databinding.demo.bean.User" />
</data>
<LinearLayout
...>
<LinearLayout style="@style/StyleItemParent">
<TextView
...
android:text="姓名:" />
<TextView
...
android:text="@{user.name}" />
</LinearLayout>
<LinearLayout ...>
<TextView
...
android:text="年齡:" />
<TextView
...
android:text="@{String.valueOf(user.age) + ` years old`}" />
</LinearLayout>
</LinearLayout>
</layout>
(2)父佈局activity_include_params_post.xml(新增名稱空間app,用於自定義屬性,然後在include標籤中傳遞資料app:user="@{user}"):
<?xml version="1.0" encoding="utf-8"?>
<!--為了傳遞資料給子佈局,需要新增自定義屬性,先新增名稱空間app-->
<layout ...
xmlns:app="http://schemas.android.com/apk/res-auto" >
<data>
<variable
name="user"
type="com.zjun.databinding.demo.bean.User" />
</data>
<RelativeLayout
...>
<!--通過app:user來傳遞資料-->
<include
layout="@layout/layout_include_params"
app:user="@{user}" />
</RelativeLayout>
</layout>
2.5 List集合顯示
這裡的List的顯示,表示把List集合中的物件單獨拎出來顯示,非介面卡Adapter。如把兩個User放入List中,然後在父佈局中把物件取出來,再傳遞給子佈局。
(1)父佈局activity_list_show.xml:
<?xml version="1.0" encoding="utf-8"?>
<layout ...
xmlns:app="http://schemas.android.com/apk/res-auto" >
<data>
<!--import匯入User類,與java程式碼的作用一樣。這樣下面可以直接引用,否則要寫完整的包名+類名。如果匯入了兩個類名一樣的類,可以使用別名alias來區分,變數中type寫別名-->
<import type="com.zjun.databinding.demo.bean.User" />
<variable
name="userList"
type="java.util.List<User>" />
</data>
<LinearLayout
... >
<!--與運算元組一樣,用中括號獲取List中的物件-->
<include
layout="@layout/layout_include_list"
...
app:user="@{userList[0]}" />
<include
layout="@layout/layout_include_list"
...
app:user="@{userList[1]}" />
</LinearLayout>
</layout>
(2)子佈局layout_include_list.xml:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="user"
type="com.zjun.databinding.demo.bean.User" />
</data>
<TextView
...
android:text="@{user.name + `[` + user.nickname + `, ` + (user.male ? `男` : `女`) + `, ` + user.age +`]`}" />
</layout>
(3)程式碼中設定資料:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityListShowBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_list_show);
List<User> userList = new ArrayList<>();
userList.add(new User("黃藥師", "東邪", true, 30));
userList.add(new User("歐陽鋒", "西毒", true, 33));
binding.setUserList(userList);
}
結果:
注意:
1.在type中的泛型同樣不能使用”<”與”>”,必須使用轉義字元"<"和">"
2.轉義字元在type中會包紅色錯誤,可忽略,編譯時能通過
3.不能直接使用android:text="@{userList[0]}",即使你想列印物件的地址,也不行。這樣使用的後果是:每個databing都報“程式包不存在”的錯誤,連之前正常的也錯了。到時候你會很懵逼的
4.子佈局中的(user.male ? `男` : `女`),必須用小括號括起來
5.android:text中的資料組合很長,但也只能寫一行,目前還不知如何分行
2.6 自定義屬性——ImageView顯示圖片
2.6.1 使用註解,在程式碼中實現自定義屬性的新增
這裡專門使用了一個類DBUtils,來封裝Databinding的註解
public class DBUtils {
/**
* 使用DataBinding來載入圖片
* 使用@BindingAdapter註解,註解值(這裡的imageUrl)可任取,註解值將成為自定義屬性
* 此自定義屬性可在xml佈局檔案中使用,自定義屬性的值就是這裡定義String型別url
* 《說明》:
* 1. 方法名可與註解名一樣,也可不一樣
* 2. 第一個引數必須是View,就是自定義屬性所在的View
* 3. 第二個引數就是自定義屬性的值,與註解值對應。這是陣列,可多個
* 這裡需要INTERNET許可權,別忘了
*
* @param imageView ImageView控制元件
* @param url 圖片網路地址
*/
@BindingAdapter({"imageUrl"})
public static void loadImage(ImageView imageView, String url) {
if (url == null) {
imageView.setImageResource(R.mipmap.ic_launcher);
} else {
Glide.with(imageView.getContext()).load(url).into(imageView);
}
}
}
2.6.2 在xml佈局檔案中使用自定義屬性
先把名稱空間寫上:xmlns:app="http://schemas.android.com/apk/res-auto"
再使用自定義屬性imageUrl
<?xml version="1.0" encoding="utf-8"?>
<layout ...
xmlns:app="http://schemas.android.com/apk/res-auto" >
<data>
<variable
name="imgUrl1"
type="String" />
<variable
name="imgUrl2"
type="String" />
</data>
<RelativeLayout
...>
<!--使用自定義屬性imageUrl-->
<ImageView
...
app:imageUrl="@{imgUrl1}" />
<ImageView
...
app:imageUrl="@{imgUrl2}" />
</RelativeLayout>
</layout>
2.6.3 程式碼中設定自定義屬性值
// 獲取Activity***Binding就省略了
binding.setImgUrl1("http://avatar.csdn.net/4/9/8/1_a10615.jpg");
binding.setImgUrl2(null);
執行結果:
![](https://img-blog.csdnimg.cn/20181108141749925.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDc4MzMxNQ==,size_16,color_FFFFFF,t_70)
2.6 ListView
ListView的展示全靠BaseAdapter,在DataBinding中也不例外。這個相對來複雜點,先把步驟寫下:
1.建立BaseAdapter的子類,因為此類可通用,所以稱CommonAdapter。內部實現核心程式碼
2.在主佈局檔案中定義變數,type型別可為BaseAdapter,也可為CommonAdapter。並把變數設定給自定義屬性adapter
3.子佈局中通過Bean來設定變數
4.在程式碼中建立CommonAdapter例項,並設定給DataBinding變數
2.6.1 建立通用的介面卡CommonAdapter
public class CommonAdapter extends BaseAdapter {
private Context mContext;
private List<User> mDataList;
private int layoutId; // 條目佈局ID
private int variableId; // DataBinding的變數ID,可通過類似R檔案的BR檔案來獲取
public CommonAdapter(Context context, List<User> dataList, int layoutId, int variableId) {
this.mContext = context;
this.mDataList = dataList;
this.layoutId = layoutId;
this.variableId = variableId;
}
@Override
public int getCount() { return mDataList.size(); }
@Override
public Object getItem(int position) { return mDataList.get(position); }
@Override
public long getItemId(int position) { return position; }
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// 沒有ViewHolder的複用,但Databinding內部已經實現了複用
ViewDataBinding binding;
if (convertView == null) {
binding = DataBindingUtil.inflate(LayoutInflater.from(mContext), layoutId, parent, false);
} else {
binding = DataBindingUtil.getBinding(convertView);
}
binding.setVariable(variableId, mDataList.get(position));
return binding.getRoot();
}
}
2.6.2 主佈局檔案中設定介面卡
<?xml version="1.0" encoding="utf-8"?>
<layout ...
xmlns:app="http://schemas.android.com/apk/res-auto"
>
<data >
<variable
name="lvAdapter"
type="com.zjun.databinding.demo.adapter.CommonAdapter" />
<!--或:type="android.widget.BaseAdapter" />-->
</data>
<RelativeLayout
...>
<!--使用自定義屬性adapter,因為有setAdapter()方法,所以無需定義-->
<ListView
...
app:adapter="@{lvAdapter}"
/>
</RelativeLayout>
</layout>
2.6.3 條目佈局中設定資料
這個簡單,上面都已經講過了的
<?xml version="1.0" encoding="utf-8"?>
<layout ...
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="user"
type="com.zjun.databinding.demo.bean.User" />
</data>
<LinearLayout
...>
<ImageView
...
app:imageUrl="@{user.icon}" />
<TextView
...
android:text="@{user.name}" />
</LinearLayout>
</layout>
2.6.4 給ListView設定Adapter
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityListViewBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_list_view);
List<User> list = new ArrayList<>();
for (int i = 0; i < 100; i++) {
// 3個網路圖片1個本地圖片,依次迴圈
User user = new User("user" + i, (i & 0x03) < 3 ? "http://avatar.csdn.net/4/9/8/1_a10615.jpg" : null);
list.add(user);
}
// 建立Adapter。BR類似與R檔案,用於儲存變數名稱。位置也與R一樣,在app包名下
CommonAdapter adapter = new CommonAdapter(this, list, R.layout.item_list_view, BR.user);
binding.setLvAdapter(adapter);
}
結果:
2.7 ListView的條目更新
在普通的ListView中,更新資料後要立馬展示到介面上,需要notifyDataSetChanged()。在但這裡,Databinding裡使用的是觀察者模式。
實現步驟:
1.在Bean類中繼承觀察者BaseObservable
2.在需要被觀察的屬性getter方法上添加註解@Bindable。因為xml中就是通過getter來獲取值的,這裡也是為了在BR檔案生成此欄位標識
3.在更新的方法中,新增屬性更新通知方法:notifyPropertyChanged(int variableId);。一般把它放在Setter方法中,因為屬性值都是通過這裡改變的。
程式碼
Bean類:
// 1、繼承BaseObservable
public class Member extends BaseObservable{
private String name;
private String icon;
public Member(String name, String icon) {
this.name = name;
this.icon = icon;
}
// 2、在屬性值的Getter上新增@Bindable註解
@Bindable
public String getName() {
return name;
}
// 3、在更新的地方新增屬性更新通知方法:notifyPropertyChanged(filedId);
public void setName(String name) {
this.name = name;
notifyPropertyChanged(com.zjun.databinding.demo.BR.name);
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
public void onItemClick(View view) {
setName(name + "【已更新】");
}
}
佈局檔案(在整個條目上設定點選事件,也可以設定在某個控制元件上):
<?xml version="1.0" encoding="utf-8"?>
<layout ...
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="member"
type="com.zjun.databinding.demo.bean.Member" />
</data>
<!--設定點選事件-->
<LinearLayout
...
android:onClick="@{member.onItemClick}">
<ImageView
...
app:imageUrl="@{member.icon}" />
<TextView
...
android:text="@{member.name}" />
</LinearLayout>
</layout>
Activity中的程式碼同上,不過我把CommonAdapter的User改成了泛型,以便通用。
結果:
2.8 新增自定義屬性用非static方法
前面我們載入圖片的時候,使用了註解@BindingAdapter({"imageUrl"}),和static靜態方法來新增自定義屬性。但static沒有非static功能多,有時就要用到物件等,怎麼辦?
DataBinding裡也可以通過component元件的方式,來實現非static來新增自定義屬性:
1.在自定義類中對新增自定義屬性的非static方法,新增@BindingAdapter註解
2.建立自定義元件類,實現DataBindingComponent。這時會自動報錯,提示需要實現獲取1中類的方法(靜態的就不需要了)。那就實現此方法
3.把元件物件設定給DataBinding
程式碼實現:
2.8.1 自定義類中新增非static方法,用於新增自定義屬性
public class NotStaticUtils {
@BindingAdapter({"imgSrc"})
public void showImg(ImageView imageView, String src) {
if (src == null) {
imageView.setImageResource(R.mipmap.ic_launcher);
} else {
Glide.with(imageView.getContext()).load(src).into(imageView);
}
}
}
2.8.2 建立自定義元件類,並實現方法
public class MyComponent implements DataBindingComponent{
private NotStaticUtils utils;
@Override
public NotStaticUtils getNotStaticUtils() {
if (utils == null) {
utils = new NotStaticUtils();
}
return utils;
}
}
2.8.3 把自定義元件設定給DataBinding
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 方法一、設定預設的元件
DataBindingUtil.setDefaultComponent(new MyComponent());
ActivityNotStaticBinding dataBinding = DataBindingUtil.setContentView(this, R.layout.activity_not_static);
// 方法二、直接在構造中傳入,這裡是單獨地給本DataBinding指定自定義元件
// ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main, new Component());
dataBinding.setSrc1("http://avatar.csdn.net/4/9/8/1_a10615.jpg");
dataBinding.setSrc2(null);
}
2.8.4 xml中使用
這個跟上面一樣,就是名稱改了一下而已。核心如下:
<variable
name="src1"
type="String" />
...
<!--使用自定義屬性imgSrc-->
<ImageView
...
app:imgSrc="@{src1}" />
2.9 在Fragment中使用
Fragment都有獨立的佈局,好像與Activity沒有什麼關係,但DataBinding中有一個方法可以繫結View:DataBindingUtil.bind(View root)。
2.9.1 佈局檔案
<layout ...>
<data>
<variable name="province" type="String" />
<variable name="city" type="String" />
</data>
<LinearLayout ...>
<TextView ...
android:text="@{province}" />
<TextView ...
android:text="@{city}" />
</LinearLayout>
</layout>
2.9.2 Fragment中繫結
獲取DataBinding的方式有三種:
1.在onCreateView通過inflate(),然後通過getRoot()返回View。然後直接設定data變數值。
2.通過bind()方法,返回佈局Binding(根據佈局自動生成的)。然後直接設定data變數值。
3.通過bind()方法,返回佈局Binding的父類ViewDataBinding。然後通過setVariable()給指定變數設定值。
private FragmentShowBinding mBinding;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_show, container, false);
// 或,在這裡獲取DataBinding
// mBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_show, container, false);
// return mBinding.getRoot();
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// 繫結View
mBinding = DataBindingUtil.bind(view);
mBinding.setProvince("浙江");
mBinding.setCity("寧波");
// 或,獲取父類ViewDataBinding,然後通過設定變數的方法
// ViewDataBinding binding = DataBindingUtil.bind(view);
// binding.setVariable(BR.province, "江西");
// binding.setVariable(BR.city, "贛州");
}
2.10 RecyclerView
RecyclerView跟ListView一樣,有一個介面卡Adapter。但要正常顯示,RecyclerView還需要一個LayoutManager(第一次就不小心就掉此坑了)。
網上有的方法是隻在item條目裡使用Databinding,RecyclerView還是通過findViewById來獲取。但這裡是Databinding,所以我這裡就不要findViewById了。
在Databinding的世界裡,如果這個View有setter方法,直接使用即可,沒有我們可以自定義屬性(見2.6)。比如要新增分割線,自己去玩吧。
直接看程式碼來看步驟邏輯:
2.10.1 activity中的佈局
activity_recycler_view.xml
<?xml version="1.0" encoding="utf-8"?>
<layout ...>
<data >
<variable
name="rvLayoutManager"
type="android.support.v7.widget.LinearLayoutManager" />
<variable
name="rvAdapter"
type="com.zjun.databinding.demo.adapter.RVAdapter" />
<!--或:type="android.support.v7.widget.RecyclerView.Adapter" />-->
</data>
<RelativeLayout ...>
<android.support.v7.widget.RecyclerView
...
app:layoutManager="@{rvLayoutManager}"
app:adapter="@{rvAdapter}"
/>
</RelativeLayout>
</layout>
2.10.2 item條目佈局
跟上面ListView的條目佈局一樣
item_recycler_view.xml
<?xml version="1.0" encoding="utf-8"?>
<layout ...>
<data>
<variable name="member" type="com.zjun.databinding.demo.bean.Member" />
</data>
<LinearLayout ...>
<ImageView ...
app:imageUrl="@{member.icon}" />
<TextView ...
android:text="@{member.name}" />
</LinearLayout>
</layout>
2.10.3 介面卡及Activity中的程式碼
有兩種寫法,第一種是官方的,第二種通用性好。官方的裡面,條目佈局都不用。
一、官方辦法
public class RVAdapter extends RecyclerView.Adapter<RVAdapter.RVHolder> {
private Context mContext;
private List<Member> mDataList;
public RVAdapter(Context context, List<Member> list) {
this.mContext = context;
this.mDataList = list;
}
@Override
public RVHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return RVHolder.create(LayoutInflater.from(mContext), parent);
}
@Override
public void onBindViewHolder(RVHolder holder, int position) {
holder.bindTo(mDataList.get(position));
}
@Override
public int getItemCount() {
return mDataList == null ? 0 :mDataList.size();
}
static class RVHolder extends RecyclerView.ViewHolder {
// 建立一個靜態獲取方法
static RVHolder create(LayoutInflater inflater, ViewGroup parent) {
ItemRecyclerViewBinding binding = ItemRecyclerViewBinding.inflate(inflater, parent, false);
return new RVHolder(binding);
}
ItemRecyclerViewBinding mBinding;
private RVHolder(ItemRecyclerViewBinding binding) {
super(binding.getRoot());
this.mBinding = binding;
}
public void bindTo(Member member) {
mBinding.setMember(member);
// 它使資料繫結重新整理所有掛起的更改。這官方的解釋好難懂,其實功能就是讓資料立即展示在佈局上
mBinding.executePendingBindings();
}
}
}
activity中使用:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityRecyclerViewBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_recycler_view);
// 模擬資料
List<Member> list = new ArrayList<>();
for (int i = 0; i < 100; i++) {
// 1個網路圖片1個本地圖片,依次迴圈
Member member = new Member("user" + i, (i & 0x01) == 0 ? "http://avatar.csdn.net/4/9/8/1_a10615.jpg" : null);
list.add(member);
}
// 設定佈局管理器,及介面卡
binding.setRvLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
binding.setRvAdapter(new RVAdapter(this, list));
}
二、通用辦法
activity中把setAdapter()程式碼,改成這句這就好了:
binding.setRvAdapter(new RVAdapter(this, list, R.layout.item_recycler_view, BR.member));
三、常見坑
DataBinding的錯誤很難找,但基本都是在xml檔案中出錯的。要仔細
3.1 Error:(8, 45) 錯誤: 程式包com.zjun.databinding.demo.databinding不存在
四、開源Demo