DataBinding系列(四):DataBinding進階之路
透過前面的學習,我們已經會使用DataBinding的一些基礎語法了,而這一篇,我就和大家一起開啟DataBinding的進階之旅,下面就讓我們透過幾個小例子一起起飛吧。
1.BindingAdapter註解設定自定義屬性
BindingAdapter對於自定義屬性是非常有用的,舉個例子,如果你的專案中用到了Glide,或者是其他的圖片載入框架,由於這些框架一般透過url給ImageView設定圖片的,但是ImageView中並沒有設定url的屬性,這個時候,BindingAdapter就派上用場了。一起來看看是如何實現的:
public class ImageHelper { /** * 1.載入圖片,無需手動呼叫此方法 * 2.使用@BindingAdapter註解設定自定義屬性的名稱,imageUrl就是屬性的名稱, * 當ImageView中使用imageUrl屬性時,會自動呼叫loadImage方法, * * @param imageView ImageView * @param url 圖片地址 */ @BindingAdapter({"imageUrl"}) public static void loadImage(ImageView imageView, String url) { Glide.with(imageView.getContext()).load(url) .placeholder(R.mipmap.fruit) .error(R.mipmap.fruit) .into(imageView); } }
使用@BindingAdapter註解設定自定義屬性的名稱,如上所示,imageUrl就是屬性的名稱,當ImageView中使用imageUrl屬性時,會自動呼叫loadImage方法,引數imageView為當前使用imageUrl屬性的ImageView,引數url為圖片地址。
xml中使用自定義屬性
<!-- 當imageUrl屬性存在時,會自動呼叫ImageHelper的loadImage方法 -->
Activity中設定圖片的url
public class BasicActivity extends AppCompatActivity { //使用者頭像 private static final String URL_USER_PIC = ""; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityBasicBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_basic); UserBean userBean = new UserBean(URL_USER_PIC, "張三", 24); binding.setUser(userBean); } }
這樣就可以在DataBinding中使用Glide來載入圖片了,此外,BindingAdapter也是允許設定多個屬性的,如下:
@BindingAdapter({"imageUrl", "placeHolder",error"}) public static void loadImage(ImageView view, String url, Drawable holderDrawable, Drawable errorDrawable) { Glide.with(imageView.getContext()) .load(url) .placeholder(holderDrawable) .error(errorDrawable) .into(imageView); }
2.資料物件 (Data Objects)
任何plain old Java object (POJO)物件都能用在 Data Binding 中,但是有個問題,當我們的資料來源發生改變的時候,UI介面上顯示的還是之前的資料,並沒有同步更新,這顯然是不行的。不知道大家還記不記得,RecyclerView或者ListView是如何更新資料的?資料是透過Adapter提供的,當資料發生改變時,我們透過notifyDatasetChanged透過UI去改變資料,這是透過一個觀察者模式來實現的,很幸運,查閱原始碼後發現DataBinding也是透過觀察者模式來實現的。
DataBinding動態更新資料的2種方式
BaseObservable
ObservableFields
BaseObservable
我們可以透過Observable的方式去通知UI重新整理資料,Observable 是一個包含新增/移除 listener 的機制的介面,為了簡化開發,Android 原生提供了一個基類 BaseObservable 來實現 listener 序號產生器制。這個類也實現了欄位變動的通知,只需要在 getter 上使用 Bindable 註解,並在 setter 中通知更新即可。
定義一個實體類,並繼承BaseObservable
public class DoubleBindBean extends BaseObservable { //BR 是編譯階段生成的一個類,功能與 R.java 類似,用 @Bindable 標記過 getter 方法會在 BR 中生成一個 entry,當我們 //透過程式碼可以看出,當資料發生變化時還是需要手動發出通知。 透過呼叫notifyPropertyChanged(BR.firstName)來通知系統 BR.firstName 這個 entry 的資料已經發生變化,需要更新 UI。 private String content; //內容 public DoubleBindBean(String content) { this.content = content; } @Bindable public String getContent() { return content; } public void setContent(String content) { this.content = content; notifyPropertyChanged(BR.content); //通知系統資料來源發生變化,重新整理UI介面 } }
BR 是編譯階段生成的一個類,功能與 R.java 類似,用 @Bindable 標記過 getxxx() 方法會在 BR 中生成一個 entry。 當資料發生變化時需要呼叫 notifyPropertyChanged(BR.content) 通知系統 BR.content這個 entry 的資料已經發生變化以更新UI。
xml:
Activity:
public class DoubleBindActivity extends AppCompatActivity implements View.OnClickListener { private DoubleBindBean doubleBindBean; private boolean flag; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityDoubleBindBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_double_bind); doubleBindBean = new DoubleBindBean("我是原始內容"); binding.setDoubleBindBean(doubleBindBean); binding.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.change_content_btn: //BaseObservable flag = !flag; if (flag) { doubleBindBean.setContent("我是更新後的內容"); } else { doubleBindBean.setContent("我是原始內容"); } break; } }
ObservableFields
如果想要省時,或者資料類的欄位很少的話,可以使用 ObservableField 以及它的派生 ObservableBoolean、 ObservableByte ObservableChar、ObservableShort、ObservableInt、ObservableLong、ObservableFloat、ObservableDouble、 ObservableParcelable 等。
它的實現就更簡潔了,如下
public class DoubleBindBean2 { //變數需要為public public final ObservableFieldusername = new ObservableField(); }
Activity:
public class DoubleBindActivity extends AppCompatActivity implements View.OnClickListener { private DoubleBindBean2 doubleBindBean2; private boolean flag2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityDoubleBindBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_double_bind); doubleBindBean2 = new DoubleBindBean2(); doubleBindBean2.username.set("我是原始內容2"); binding.setDoubleBindBean2(doubleBindBean2); binding.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.change_content_btn2: //ObservableFields flag2 = !flag2; if (flag2) { doubleBindBean2.username.set("我是更新後的內容2"); } else { doubleBindBean2.username.set("我是原始內容2"); } break; } } }
Observable Collections
除了支援ObservableField,ObservableBoolean,ObservableInt等基礎變數型別以外,當然也支援集合框架拉,比如:ObservableArrayMap,ObservableArrayList。使用和普通的Map、List基本相同
" /> " />
Activity:
public class DoubleBindActivity extends AppCompatActivity implements View.OnClickListener { private ObservableArrayListlist=new ObservableArrayList(); private ObservableArrayMap map = new ObservableArrayMap(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityDoubleBindBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_double_bind); list.add("list1"); list.add("list2"); binding.setList(list); map.put("key0","key0_value0"); map.put("key1","key1_value1"); binding.setMap(map); binding.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.change_content_btn3: list.set(0,"after change list"); break; case R.id.change_content_btn4: map.put("key0","after change key0_value0"); break; } } }
View with ID
如果我們需要在Activity中獲取某個View來進行一些操作,那該怎麼辦呢?別擔心,有辦法,佈局中每一個帶有 ID 的 View,都會生成一個 public final 欄位。binding 過程會做一個簡單的賦值,在 binding 類中儲存對應 ID 的 View。這種機制相比呼叫 findViewById 效率更高。舉個例子:
Activity
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main); binding.userName.setText("content") } }
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2894/viewspace-2813525/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Android DataBinding 從入門到進階Android
- Android DataBinding 從入門到進階(2)Android
- Android Jetpack - DataBindingAndroidJetpack
- MVVM 中的DatabindingMVVM
- MVVM模式--DataBinding的使用MVVM模式
- databinding的點選事件事件
- DataBinding基礎使用一
- DataBinding基礎使用二
- DataBinding基礎使用三
- Android:DataBinding的一二事Android
- Android DataBinding之初體驗Android
- React 進階之路(四)React
- MVVM架構篇之DataBinding(-)MVVM架構
- Android架構元件-DataBinding的使用Android架構元件
- Android Studio: Kotlin使用DataBinding異常AndroidKotlin
- Android Jetpack(2):DataBinding的基本使用AndroidJetpack
- 雞你太美之 Kotlin 和 DatabindingKotlin
- Databinding 雙向繫結詳解
- Android結合DataBinding封裝的BaseBindingAdapterAndroid封裝APT
- DataBinding資料繫結基本講解
- Python 從入門到進階之路(四)Python
- JetPack 學習筆記:Databinding 與響應式Jetpack筆記
- Android MVVM探索(三) - ViewModel,DataBinding,LiveData混合三打AndroidMVVMViewLiveData
- Android開發教程-使用DataBinding(六)RecyclerViewAdapter中的使用AndroidViewAPT
- Android開發教程-使用DataBinding(五)資料繫結Android
- Android JetPack~ DataBinding(資料繫結)(一) 整合與使用AndroidJetpack
- koa2 從入門到進階之路 (四)
- 每日一問:不一樣的角度吐槽下 DataBinding
- 封裝DataBinding讓你少寫萬行程式碼封裝行程
- Typescript進階之路TypeScript
- Android高階進階之路【四】一文讀懂 Handler 機制Android
- 直播系統平臺搭建,DataBinding自定義雙向繫結
- 使用AndroidX + ViewModel + LiveData + DataBinding等元件搭建的MVVM快速開發框架AndroidViewLiveData元件MVVM框架
- React 進階之路(六)React
- React 進階之路(五)React
- Vue 進階之路(十四)Vue
- Django進階之路(一)Django
- React 進階之路(三)React