Android Jetpack - DataBinding
簡介
使用宣告性格式(而非程式化地)將佈局中的介面元件繫結到應用中的資料來源,即在xml裡面就將view和資料繫結,然後當資料發生變化時view能自動變。
ViewBinding和DataBinding相輔相成的,它們都會生成額外的一個binding類,如果頁面需要資料就使用DataBinding,如果頁面簡單使用ViewBinding更快,不管用哪個,findViewById可以告別了
簡單使用:(不像ViewBinding那樣對AS版本有要求,Android Plugin for Gradle 版本在1.5.0以上即可)
- 在需要用的module的build.gradle中新增
android {
...
dataBinding {
enabled = true
}
}
- 寫一個bean類(看需求,這邊主要是說明頁面需要的資料)
@Entity
public class User {
@PrimaryKey(autoGenerate = true)
public int uid;
@ColumnInfo(name = "first_name", defaultValue = "a")
public String firstName;
@ColumnInfo(name = "last_name")
public String lastName;
}
- 在xml中
<!--如果使用databinding根節點都變成了layout-->
<layout
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">
<!--這邊宣告該頁面需要使用的資料-->
<data>
<variable
<!--變數名-->
name="user"
<!--變數型別-->
type="com.dean.mh_calendar.model.User" />
</data>
<!--這邊和之前一樣佈局-->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_first_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
<!--在需要的地方直接使用資料-->
android:text="@{user.firstName}"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<TextView
android:id="@+id/tv_last_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.lastName}"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_first_name"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
繫結xml中使用的資料有自動檢測空指標功能,如果為null那麼賦予的值就是null,如果是int等字元型,預設值是0
在繫結的xml中使用資料和直接在java中使用基本一樣,只是不可以使用new、this、super 和 顯式泛型呼叫
比如可以:
android:text="@{String.valueOf(index + 1)}"
android:visibility="@{age > 13 ? View.GONE : View.VISIBLE}"
android:transitionName='@{"image_" + id}'
除此以外,還可以使用一些新的運算子
- ??:Null 合併運算子
android:text="@{user.firstName ?? user.lastName}"
當user.firstName為null時使用user.lastName,不為null使用user.firstName
- 檢視引用:按 ID 引用佈局中的其他檢視
<EditText
android:id="@+id/example_text"
android:layout_height="wrap_content"
android:layout_width="match_parent"/>
<TextView
android:id="@+id/example_output"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
<!--在此處引用了上面EditText的Text值,引用名稱按照駝峰命名法引用-->
android:text="@{exampleText.text}"/>
- 使用集合
集合使用都用[]來取值,但是在data中引入的時候需要注意
<data>
<import type="java.util.List"/>
<!-- < 必須 轉義成 <-->
<variable name="list" type="List<String>"/>
<variable name="index" type="int"/>
</data>
android:text="@{list[index]}"
- 字串字面量
如果表示式裡面要用“”或者’’,外層就可以與之相反,即
android:text='@{map["firstName"]}'
android:text="@{map[`firstName`]}"
- 資源引用
需要使用資源時可以直接使用
android:padding="@{large ? @dimen/largePadding : @dimen/smallPadding}"
如果是需要引數可以直接傳,比如格式字串
android:text="@{@string/nameFormat(firstName, lastName)}"
當一個複數帶有多個引數時,您必須傳遞所有引數
Have an orange
Have %d oranges
android:text="@{@plurals/orange(orangeCount, orangeCount)}"
- 事件處理
根據需要在xml中有兩種事件繫結處理方式:傳統的方法引用和監聽器繫結
它們的區別是:方法引用無法自定義入參,並且它是直接繫結方法,無論事件有沒有發生;而監聽器繫結可以自定義入參(兩種方式的是無法修改返回的),並且只有當事件發生時才繫結方法,還可以處理一些邏輯程式碼,但是谷歌不建議有業務相關的或者大量邏輯的
監聽器繫結:
- 寫事件處理方法,在定義方法時可以多一些引數
public class MainActivity extends AppCompatActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main3);
mBinding.setHanldeEvent(new HandleEvent());
}
public class HandlerEvent {
public boolean backBtnOnLongClick(View view){
Toast.makeText(view.getContext(),"backBtnOnLongClick",Toast.LENGTH_SHORT).show();
return true;
}
public void backBtnOnClick(View view, String text){
Toast.makeText(view.getContext(),"backBtnOnClick",Toast.LENGTH_SHORT).show();
}
}
}
- 在檢視中加入
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="hanldeEvent" type="com.dean.smartapp.Main3Activity.HandleEvent" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="事件繫結"
<!--使用時傳參,這邊的view2FunParams就是傳遞的text引數,必須使用"轉義"號-->
android:onClick="@{(view)->hanldeEvent.backBtnOnClick(view,"view2FunParams")}"
android:onLongClick="@{hanldeEvent::backBtnOnLongClick}"/>
</LinearLayout>
</layout>
- 類名衝突
當匯入不同包下的類時會有類名衝突,這時可以使用alias來讓其中一個宣告別名
<data>
<import type="java.util.List" alias="system_list"/>
</data>
- 當databinding遇到包含include 和 merge
當有子佈局時,繫結的資料可以直接傳遞
<!--父佈局-->
<?xml version="1.0" encoding="utf-8"?>
<layout
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">
<data>
<variable name="user" type="com.dean.mh_calendar.model.User" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<include android:id="@+id/include_layout"
layout="@layout/test_include"
<!--將值傳遞下去-->
app:user="@{user}"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
<!--子佈局-->
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable name="user" type="com.dean.mh_calendar.model.User" />
</data>
<!--此處merge會報錯,但是編譯執行沒有問題-->
<merge
tools:parentTag="android.support.constraint.ConstraintLayout">
<TextView
android:id="@+id/tv_include_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.firstName + user.lastName}"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</merge>
</layout>
如果子佈局裡面還有子佈局,則不能直接在merge下寫include
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="user"
type="com.dean.mh_calendar.model.User" />
</data>
<merge>
<include android:id="@+id/include_layout"
layout="@layout/test_include2"
app:user="@{user}"/>
</merge>
</layout>
這樣寫在編譯時會報錯Data binding does not support include elements as direct children of a merge element.這時可以在include外套一層佈局
- 在介面控制器中繫結資料
//一旦在xml中使用layout作為根佈局,會自動生成相應的繫結類
private ActivityMain3Binding mBinding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//通過DataBindingUtil拿到生成的繫結類
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main3);
mBinding.setUser(users.get(0));
}
在activity中使用的是DataBindingUtil.setContentView(this, R.layout.activity_main3);獲取繫結類
在fragment或者recycleView的adapter中使用DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false);獲取繫結類
- 使用可觀察的資料物件
上面這些只是在螢幕上展示資料,還可以讓可觀察物件繫結到介面,這時一旦該資料物件的屬性發生更改,介面會自動更新。
相關文章
- Android Jetpack(2):DataBinding的基本使用AndroidJetpack
- Android JetPack~ DataBinding(資料繫結)(一) 整合與使用AndroidJetpack
- JetPack 學習筆記:Databinding 與響應式Jetpack筆記
- Android:DataBinding的一二事Android
- Android DataBinding之初體驗Android
- Android Jetpack 之 LiveDataAndroidJetpackLiveData
- Android Jetpack之ViewModelAndroidJetpackView
- Android Jetpack 之 LifecycleAndroidJetpack
- Android Jetpack 之 ViewModelAndroidJetpackView
- Android架構元件-DataBinding的使用Android架構元件
- Android Studio: Kotlin使用DataBinding異常AndroidKotlin
- Android Jetpack Navigation基本使用AndroidJetpackNavigation
- Android結合DataBinding封裝的BaseBindingAdapterAndroid封裝APT
- Android DataBinding 從入門到進階Android
- Android Jetpack Architecture原理之ViewModelAndroidJetpackView
- Android Jetpack - Fragment官方說明AndroidJetpackFragment
- Android Jetpack Compose 引入示例工程AndroidJetpack
- 【Android Jetpack教程】ViewModel原理分析AndroidJetpackView
- Android Jetpack - Android TV 應用開發教程AndroidJetpack
- Android DataBinding 從入門到進階(2)Android
- Android Jetpack 之Navigation Architecture Component使用AndroidJetpackNavigation
- Android Sunflower 帶您玩轉 JetpackAndroidJetpack
- Android Jetpack系列——ViewModel原始碼分析AndroidJetpackView原始碼
- 玩轉Android Jetpack系列之ViewModeAndroidJetpackView
- Android Jetpack - Emoji表情符號初探AndroidJetpack符號
- Android Jetpack 架構元件之 NavigationAndroidJetpack架構元件Navigation
- Android技術棧(四)Android Jetpack MVVM 完全實踐AndroidJetpackMVVM
- Android Jetpack元件之Lifecycles庫詳解AndroidJetpack元件
- Android Jetpack Navigation 深入體驗報告AndroidJetpackNavigation
- Android JetPack~ ViewModel (一) 介紹與使用AndroidJetpackView
- Android JetPack~ LiveData (一) 介紹與使用AndroidJetpackLiveData
- Android Jetpack架構元件(七)之WorkManagerAndroidJetpack架構元件
- Android MVVM探索(三) - ViewModel,DataBinding,LiveData混合三打AndroidMVVMViewLiveData
- Android開發教程-使用DataBinding(六)RecyclerViewAdapter中的使用AndroidViewAPT
- Android開發教程-使用DataBinding(五)資料繫結Android
- DataBinding系列(四):DataBinding進階之路
- Android Jetpack元件 - ViewModel,LiveData使用以及原理AndroidJetpack元件ViewLiveData
- Android Jetpack - 使用 Navigation 管理頁面跳轉AndroidJetpackNavigation