DataBinding的學(xué)習(xí)【2018-07-17】

一剃法、基本的使用姿勢

1. module的build.gradle文件加上一行配置代碼

android {

? ? ...? ? dataBinding {

? ? ? ? enabled = true

? ? }}

2. 創(chuàng)建布局文件

只需要在之前布局的基礎(chǔ)上试溯,外層嵌套 即可艾少。



? ? ? ? ? ? name="student"

? ? ? ? ? ? type="com.xiaweizi.bean.Student"/>





? ? ? ? ? ? ? ? name="student"

? ? ? ? ? ? ? ? type="Student"/>

? ? ? ? -->



? ? ? ? android:layout_width="match_parent"

? ? ? ? android:layout_height="match_parent"

? ? ? ? android:gravity="center_horizontal"

? ? ? ? android:orientation="vertical">


因?yàn)閄ML是不支持自定義導(dǎo)包的驳阎,所以通過import先導(dǎo)包,如果類名相同的話可以通過alias進(jìn)行區(qū)分:

? ? ? ? alias="MyView"/>

? ? name="view1"

? ? type="View"/>

? ? name="view2"

? ? type="MyView"/>

這個時候會在app\build\generated\source\debug\包名路徑下生成對應(yīng)的binding類,命名方式囱皿,舉個例子最為直接:

原XML名:activity_main? ----> 生成對應(yīng)的binding名: ActivityMainBinding

3. Activity中替換原來的setContentView()代碼

ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);

二哗魂、事件的binding

1.單向binding

案例1:(view id)

? ? android:id="@+id/tv_content"

? ? android:text="@{student.name}"

? ? android:layout_width="match_parent"

? ? android:layout_height="50dp"/>

在代碼中通過binding直接可以獲取到這個TextView

mBinding.tvContent

案例2:(click event)

①定義按鍵處理的類型

public class Presenter {

? ? ? //Android標(biāo)準(zhǔn)的事件類型肛走,需要注意Method中的參數(shù)和api中的保持一致

public void onTextChanged(CharSequence s, int start, int before, int count) {

? ? ? ? ? ? employee.setFirstName(s.toString());

? ? ? ? ? ? employee.setFired(!employee.isFired.get());

? ? ? ? ? ? //binding.setEmployee(employee);

? ? ? ? }

//自定義的事件類型

? ? ? ? public void onClickListenerBinding(Employee employee) {

? ? ? ? ? ? Toast.makeText(SimpleActivity.this, employee.getLastName(),

? ? ? ? ? ? ? ? ? ? Toast.LENGTH_SHORT).show();

? ? ? ? }

? ? }

②、在xml中聲明制定的案件處理的類型和指定事件


? ? ? ? ? ? name="presenter"

? ? ? ? ? ? type="com.github.markzhai.sample.SimpleActivity.Presenter"/>


//Android標(biāo)準(zhǔn)的事件類型

? ? ? ? ? ? android:id="@+id/et_first_name"

? ? ? ? ? ? android:layout_width="match_parent"

? ? ? ? ? ? android:layout_height="wrap_content"

? ? ? ? ? ? android:hint="輸入 First Name jiaoyin"

? ? ? ? ? ? android:onTextChanged="@{presenter::onTextChanged}"/>

//自定義的事件類型

? ? ? ? ? ? android:layout_width="wrap_content"

? ? ? ? ? ? android:layout_height="wrap_content"

? ? ? ? ? ? android:layout_marginLeft="5dp"

? ? ? ? ? ? android:onClick="@{() -> presenter.onClickListenerBinding(employee)}"

? ? ? ? ? ? android:text="@{employee.lastName}"/>

2.雙向binding

之前說的單向綁定录别,即當(dāng)數(shù)據(jù)變化朽色,通過mBinding.setStudent(student)方式驅(qū)動UI的改變

而雙向綁定,無論View還是ViewModel誰改變组题,都會驅(qū)動另一方的改變葫男,實(shí)現(xiàn)雙向綁定有兩種方式:繼承BaseObservable或者使用ObservableField創(chuàng)建成員變量。

案例1:繼承BaseObservable:

public class Employee extends BaseObservable {

? ? private String mLastName;

? ? private String mFirstName;

? ? public Employee(String lastName, String firstName) {

? ? ? ? mLastName = lastName;

? ? ? ? mFirstName = firstName;

? ? ? ? isFired.set(false);

? ? }

? ? @Bindable

? ? public String getLastName() {

? ? ? ? return mLastName;

? ? }

? ? public void setLastName(String lastName) {

? ? ? ? mLastName = lastName;

? ? ? ? notifyPropertyChanged(com.github.markzhai.sample.BR.lastName);

//notifyChange();

? ? }

}

這個時候當(dāng)調(diào)用setLastName()方法,不僅數(shù)據(jù)改變往踢,UI中的TextView內(nèi)容也會隨之改變腾誉。

我們可以發(fā)現(xiàn)有兩個方法:notifyPropertyChanged()和notifyChange,一個是更新指定的變量,第二個是更新所有該ViewModel中的對象峻呕。

而notifyPropertyChanged(int fieldId)里面?zhèn)鞯膮?shù)利职,即上面通過@Bindable注解創(chuàng)建對應(yīng)的變量id。

案例2:使用ObservableField創(chuàng)建成員變量

public class Employee extends BaseObservable {

? ? private String mLastName;

? ? private String mFirstName;

? ? public ObservableArrayMap user = new ObservableArrayMap<>();

? ? private String mAvatar;

? ? public ObservableBoolean isFired = new ObservableBoolean();

? ? public Employee(String lastName, String firstName) {

? ? ? ? mLastName = lastName;

? ? ? ? mFirstName = firstName;

? ? ? ? isFired.set(false);

? ? }

? ? public void setFired(boolean fired) {

? ? ? ? isFired.set(fired);

? ? }

? ? @Bindable

? ? public String getAvatar() {

? ? ? ? return mAvatar;

? ? }

? ? public void setAvatar(String avatar) {

? ? ? ? mAvatar = avatar;

? ? }

}

通過使用ObservableField創(chuàng)建的對象作用相當(dāng)于第一種的方案瘦癌,支持ObservableInt猪贪、ObservableBoolean或者是ObservableField指定的類型、ObservableArrayMap讯私、ObservableArrayList等热押。

ObservableField內(nèi)部已經(jīng)封裝了get和set方法,如果成員變量是public屬性斤寇,直接通過

mStudent.name.set("shabi");

String name = mStudent.name.get();

設(shè)置和獲取對應(yīng)的成員變量的值桶癣。

其他用法:

2.?ViewStub和include

dataBinding同樣是支持ViewStub的,使用起來也很簡單娘锁,直接貼代碼了牙寞。

? ? android:id="@+id/view_stub"

? ? android:layout_width="wrap_content"

? ? android:layout_height="wrap_content"

? ? android:layout="@layout/viewstub"/>

代碼中:

View inflate = binding.viewStub.getViewStub().inflate();

inflate即為替代ViewStub的View.

至于include更簡單,用法跟以前是差不多莫秆,唯一不同的是可以將ViewModel傳到下一個XML中:

bind:student="@{student}"/>

layout_include中同樣可以共享student這個對象间雀。

3.??@BindingConversion

dataBinding還支持對數(shù)據(jù)的轉(zhuǎn)換,或者是類型的轉(zhuǎn)換

4.自定義的屬性之BindingAdapter的使用

案例:

//1镊屎、xml定義

android:id="@+id/username" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="35sp"

android:text="@{user.name}"/>

//2惹挟、BindingAdapter自定義

public class TextViewBindingAdapter {

@BindingAdapter("android:text")

public static voidsetText(TextView view, CharSequence text) {

? ? ? ? final CharSequence oldText = view.getText();

? ? ? ? if (text == oldText || (text == null && oldText.length() == 0)) {

? ? ? ? ? ? return;

? ? ? ? }

? ? ? ? if (text instanceof Spanned) {

? ? ? ? ? ? if (text.equals(oldText)) {

? ? ? ? ? ? ? ? return; // No change in the spans, so don't set anything.

? ? ? ? ? ? }

? ? ? ? } else if (!haveContentsChanged(text, oldText)) {

? ? ? ? ? ? return; // No content changes, so don't set anything.

? ? ? ? }

? ? ? ? view.setText(text);

? ? }

}

//3、更新User的name的值

User user = new User(name, age);

mBinding.setUser(user);

databinding框架缝驳,會做如下幾件事情:

①計(jì)算出@{user.name} 表達(dá)式的值连锯;

②尋找合適的BindingAdapter归苍,如果找到,就調(diào)用它對應(yīng)BindingAdapter里面的(setText)方法运怖;

③如果沒有找到合適的BindingAdapter霜医,就在View上尋找合適的(setText)方法調(diào)用;

如此類推驳规,可以自定義BindingAdapter..............

5. DataBindingComponent

通過BindingAdapter是可以增加一些自定義的屬性或者是修改Android原生的屬性,但是它有一個弊端署海,就是全局修改所有的相關(guān)屬性吗购,不過配合上DataBindingComponent就可以解決這個問題。

6.RecyclerView中的應(yīng)用

案例:

//xml定義部分:

? ? xmlns:android="http://schemas.android.com/apk/res/android">



? ? ? ? ? ? name="presenter"

? ? ? ? ? ? type="com.github.markzhai.sample.ListActivity.Presenter"/>



? ? ? ? android:layout_width="match_parent"

? ? ? ? android:layout_height="match_parent"

? ? ? ? android:orientation="vertical">

? ? ? ? ? ? android:id="@+id/recycler_view"

? ? ? ? ? ? android:layout_width="match_parent"

? ? ? ? ? ? android:layout_height="match_parent"/>


//初始化 recycleview 和 adapter部分

protected void onCreate(@Nullable Bundle savedInstanceState) {

? ? ? ? super.onCreate(savedInstanceState);

? ? ? ? mBinding = DataBindingUtil.setContentView(this, R.layout.activity_list);

? ? ? ? mBinding.setPresenter(new Presenter());

mBinding.recyclerView.setLayoutManager(new LinearLayoutManager(this));

mEmployeeAdapter = newEmployeeAdapter(this);

mBinding.recyclerView.setAdapter(mEmployeeAdapter);


? ? ? ? List demoList = new ArrayList<>();

? ? ? ? demoList.add(new Employee("Zhai", "Mark", false));

? ? ? ? demoList.add(new Employee("Zhai2", "Mark2", false));

? ? ? ? demoList.add(new Employee("Zhai3", "Mark3", true));

? ? ? ? demoList.add(new Employee("Zhai4", "Mark4", false));

mEmployeeAdapter.addAll(demoList);

? ? }

//自定義viewholder部分

public class BindingViewHolder

? ? ? ? extends RecyclerView.ViewHolder {

? ? private T mBinding;

? ? public BindingViewHolder(T binding) {

//注意砸狞,這里是要設(shè)置 binding的rootview 給到viewholder中

? ? ? super(binding.getRoot());

? ? ? ? mBinding = binding;

? ? }

? ? public T getBinding() {

? ? ? ? return mBinding;

? ? }

}

//自定義adapter部分

public class EmployeeAdapter extends RecyclerView.Adapter {

@Override

? ? public BindingViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

? ? ? ? ViewDataBinding binding;

? ? ? ? if (viewType == ITEM_VIEW_TYPE_ON) {

//加載出 DataBinding的對象

binding =DataBindingUtil.inflate(mLayoutInflater,

? ? ? ? ? ? ? ? ? ? R.layout.item_employee, parent, false);

? ? ? ? } else {

binding =DataBindingUtil.inflate(mLayoutInflater,

? ? ? ? ? ? ? ? ? ? R.layout.item_employee_off, parent, false);

? ? ? ? }

//注意

returnnew BindingViewHolder(binding);

? ? }

? ? @Override

? ? public void onBindViewHolder(BindingViewHolder holder, int position) {

? ? ? ? final Employee employee = mEmployeeList.get(position);

//注意:

//設(shè)置 variable變量捻勉,并內(nèi)部有去做 notifyDataChange的動作

? ? ? ? holder.getBinding().setVariable(com.github.markzhai.sample.BR.item, employee);

//execute,以便馬上更新

? ? ? ? holder.getBinding().executePendingBindings();

? ? }

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市刀森,隨后出現(xiàn)的幾起案子踱启,更是在濱河造成了極大的恐慌,老刑警劉巖研底,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件埠偿,死亡現(xiàn)場離奇詭異,居然都是意外死亡榜晦,警方通過查閱死者的電腦和手機(jī)冠蒋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來乾胶,“玉大人抖剿,你說我怎么就攤上這事∈读” “怎么了斩郎?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長喻频。 經(jīng)常有香客問我缩宜,道長,這世上最難降的妖魔是什么半抱? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任脓恕,我火速辦了婚禮,結(jié)果婚禮上窿侈,老公的妹妹穿的比我還像新娘炼幔。我一直安慰自己,他們只是感情好史简,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布乃秀。 她就那樣靜靜地躺著肛著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪跺讯。 梳的紋絲不亂的頭發(fā)上枢贿,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機(jī)與錄音刀脏,去河邊找鬼局荚。 笑死,一個胖子當(dāng)著我的面吹牛愈污,可吹牛的內(nèi)容都是我干的耀态。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼暂雹,長吁一口氣:“原來是場噩夢啊……” “哼首装!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起杭跪,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤仙逻,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后涧尿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體系奉,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年姑廉,在試婚紗的時候發(fā)現(xiàn)自己被綠了喜最。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡庄蹋,死狀恐怖瞬内,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情限书,我是刑警寧澤虫蝶,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站倦西,受9級特大地震影響能真,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜扰柠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一粉铐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧卤档,春花似錦蝙泼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽织鲸。三九已至,卻和暖如春溪胶,著一層夾襖步出監(jiān)牢的瞬間搂擦,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工哗脖, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瀑踢,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓才避,卻偏偏與公主長得像丘损,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子工扎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容