最近在看一些人寫的代碼,發現不少都有用到 DataBinding,往往看到 DataBinding 相關的代碼看不懂,摸不透,實在是難受啊,但是怎麼辦呢,誰讓本身不會的呢。沒辦法開始學吧,不要求會太多,總得能看的懂人家寫的是啥意思吧。java
本篇難度屬於 DataBinding 入門級別,若是有什麼錯誤,還請指正。要學習 DataBinding 最好的教材仍是經過官方給的實例教程。android
正式開始以前呢,老是得添加依賴,不過,DataBinding 的依賴可不像 RxJava 或是其餘庫經過引入兩行依賴,而是經過在 app.gradle 文件中引入下面的配置:git
android {
...
dataBinding {
enabled = true
}
}
複製代碼
有了依賴以後,咱們就能夠開始了,如今想象一個場景,咱們須要把一段文字顯示在 TextView 上。以前,咱們都是經過 findViewById,而後 setText,現現在來一塊兒看看 DataBinding 是怎麼作的吧。github
首先,咱們須要把佈局文件的結構進行改造一下,改形成這樣的結構。express
<layout>
<data>
</data>
<ViewGroup>
</ViewGroup>
</layout>
複製代碼
Android Studio 對 DataBinding 有自動替換的支持。app
替換以後的 ViewGroup 就是以前的根佈局,data 節點內用於定義數據。框架
<data>
<variable name="content" type="String" />
</data>
複製代碼
以此形式定義的變量 content 等價於 String content
。拿到了 content 這個變量,緊接着就須要設置到 TextView 上。設置 Text,使用的屬性是 android:text=""
至於填入的值,就是 content,不過語法上稍有不一樣,android:text="@{content}"
其中 @
以及{}
是用於包裹其中的值,以此來區分開 android:text="content"
。ide
Databinding 使用這種語法來設置內容,事實上這種表達方法不只僅用於設置個字符串,還支持表達式,更多內容請參考官方文檔。本文也會介紹一些。佈局
事實上,咱們更多時候會把 content 做爲一個類的成員變量。只要將 variable 的 type 屬性改爲對應的類名,同時在 TextView 上改成 android:text="@{detail.content}"
便可。post
<data>
<variable name="detail" type="me.monster.blogtest.model.MomentDetail" />
</data>
複製代碼
在佈局文件中定義好了變量,如今咱們該回到 Java 文件中將佈局文件使用 DataBinding 進行綁定上數據了。
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
FragmentDetailBinding viewDataBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_detail, container, false);
View root = viewDataBinding.getRoot();
mMomentDetail = new MomentDetail();
mMomentDetail.setContent("使用 DataBinding");
viewDataBinding.setDetail(mMomentDetail);
return root;
}
複製代碼
- 這段代碼是使用在 Fragment 中的,若是在 Activity 中,則使用
DataBinding.Util.setContentView(Activity activity, int layoutId)
這個方法。- FragmentDetailBinding 這個類是根據佈局文件生成的,類名的規則是佈局文件的文件名+Binding;
DataBinding 這樣使用,好像不太夠平常使用。當 mMomentDetail 內部的 content 發生改變時,TextView 能自動更新嗎?暫時不行,想讓 TextView 自動更新 mMomentDetail 的 content 的內容,咱們還須要另外的一些東西。
要想及時更新 mMomentDetail 的 content 內容,按照以往的作法,就是在更新 mMomentDetail 的 content 內容時,手動調用 setText()
這個方法。如今有了 DataBinding 就不用了。咱們能夠把 mMomentDetail 的 content 定義爲一種可觀察其變化的類型,而後經過 DataBinding 就能自動完成對 TextView 上內容的更新。
public class MomentDetail {
private String content;
public String getContent() {
return content == null ? "" : content;
}
public void setContent(String content) {
this.content = content;
}
}
複製代碼
這個是 TextView 不能自動更新內容的 MomentDetail 類,要想讓 TextView 自動更新,只須要把 content 的類型改變便可。改成 ObservableField<String> content
。
private ObservableField<String> content = new ObservableField<>();
public ObservableField<String> getContent() {
return content;
}
public String getContentValue() {
return content.get();
}
public void setContent(String content) {
this.content.set(content);
}
複製代碼
與普通的 String 類型不一樣的是,想要改變 content 的值,須要調用 ObservableField.set(T t)
方法,獲取其中的值則使用 ObservableField.get()
方法。
DataBinding 還包含了一些其餘的類,都是同樣的用法。
我在寫這篇博客的時候,使用 Handler 延遲幾秒鐘對 MomentDetail 進行修改,用於模擬點擊事件。
當咱們用於觀察的數據較多的時候,還能夠經過將自定義的數據類繼承 BaseObservable ,產生繼承關係以後,數據類中的成員變量都可以在發生改變時自動應用到 View 上。
public class MomentDetail extends BaseObservable {
private String moment;
private int goodCount;
@Bindable
public String getMoment() {
return moment == null ? "" : moment;
}
@Bindable
public int getGoodCount() {
return goodCount;
}
public void setContent(String msg) {
this.moment = msg;
notifyPropertyChanged(BR.moment);
}
public void updateGood(int count) {
goodCount = count;
notifyPropertyChanged(BR.goodCount);
}
}
複製代碼
跟其餘的數據類沒有什麼太大的差距,只是多了一個註解 @Bindable
以及在成員變量進行更改後進行更新 notifyPropertyChanged()
。不過,Google 仍是推薦使用 LiveData 配合使用。
public class MomentViewModel extends ViewModel {
private MutableLiveData<String> name = new MutableLiveData<>("Abs");
private MutableLiveData<Integer> good = new MutableLiveData<>();
public void setNameValue(String value) {
name.setValue(value);
}
public MutableLiveData<String> getName() {
return name;
}
public MutableLiveData<Integer> getGood() {
return good;
}
public void setGoodValue(int goodValue) {
good.setValue(goodValue);
}
}
複製代碼
相應的,佈局文件中也要進行更改數據類型。
<variable name="viewModel" type="me.monster.blogtest.model.MomentViewModel" />
複製代碼
DataBinding 設置 View 的 text
,textColor
等屬性均可以直接經過相似 android:text="@{viewModel.name}"
這種形式來進行操做,那若是想對控件進行點擊事件的監聽怎麼辦呢?也不麻煩,咱們只須要提供一個用於處理點擊結果的方法便可。
例如,咱們有一個 TextView 用於進行點擊,並將點擊次數顯示在當前 TextView 上。
public void upGood() {
good.setValue(good.getValue() == null ? 1 : good.getValue() + 1);
}
複製代碼
<TextView android:id="@+id/iv_good" android:layout_width="wrap_content" android:layout_height="40dp" android:drawableStart="@drawable/ic_good" android:drawablePadding="8dp" android:gravity="center" android:onClick="@{() -> viewModel.upGood()}" android:text="@{String.valueOf(viewModel.good)}" />
複製代碼
不過,DataBinding 雖然挺好的,可是仍是有些不足,好比經過 Glide 這種第三方框架加載圖片,仍是得 findViewById
,事實上,DataBinding 提供了另外一種解決思路,經過將一個靜態方法加上註解,而後就能夠在 View 中進行使用。
@BindingAdapter({"imageRes"})
public static void loadImage(ImageView imageView, int resId) {
Glide.with(imageView)
.load(resId)
.into(imageView);
}
複製代碼
<ImageView android:id="@+id/iv_avatar" imageRes="@{viewModel.avatar}" android:layout_width="50dp" android:layout_height="50dp" android:src="@mipmap/avatar_1" />
複製代碼
BindAdapter 還有更多其餘用法,請參考官方文檔。
總體來講,DataBinding 不難,並且入門也挺簡單的,不過,剛上手,不少時候摸不到頭腦。不過,它的好處也很明顯,在 Fragment 或是 Activity 中沒有使用任何直接或是間接的 findViewById
操做。保證了 Activity 與 Fragment 的簡潔,使其能更好的專一於頁面的跳轉及數據的處理,假若配合着 Jetpack 的其餘組件協同開發,估計會更高效些。
本文旨在學習如何簡單的使用 DataBinding,主體內容較爲簡單,實際上,平常開發中還會常常用到 RecyclerView 及其餘功能,DataBinding 也能提供很好的支持,有興趣或是須要的話能夠自行查閱官方文檔。
文章首發於我的博客,文中全部代碼均已上傳至 GitHub,代碼分支爲:dataBinding。
相關文章推薦:
本文封面圖:Photo by Paul Schafer on Unsplash。