如何通過Data Binding提升擼碼逼格(進階篇)

2021-02-07 安卓巴士Android開發者門戶
前言

前段時間,完結了一篇Data Binding前篇,地址如下:

如何通過Data Binding提升擼碼逼格(基礎篇)

而今,我們一起來學習下,有關Data Binding進階用法。

發車了,來來來一、notifyPropertyChanged方式更新指定數據

首先,來簡單介紹下Observable:

先來一個小例子:

那麼針對這個需求,我們使用Observable即可分分鐘搞定。這裡,大家可以簡單理解為,這個就是負責數據更新~

下面來個Demo試試:

Step 1: 實體類繼承BaseObservable

package com.hlq.databindingdemo.bean;
import android.databinding.BaseObservable;
import android.databinding.Bindable;
import com.hlq.databindingdemo.BR;

public class ClassBean extends BaseObservable {
   private String classNo;
   private String classNum;
   private String className;
   public ClassBean(String className) {
       this.className = className;
   }
   public ClassBean(String className, String classNum) {
       this.className = className;
       this.classNum = classNum;
   }
   public ClassBean(String classNo, String classNum, String className) {
       this.classNo = classNo;
       this.classNum = classNum;
       this.className = className;
   }
   @Bindable
   public String getClassNo() {
       return classNo;
   }
   public void setClassNo(String classNo) {
       this.classNo = classNo;
   }
   @Bindable
   public String getClassName() {
       return className;
   }
   public void setClassName(String className) {
       this.className = className;
   }
   @Bindable
   public String getClassNum() {
       return classNum;
   }
   public void setClassNum(String classNum) {
       this.classNum = classNum;
   }
}

Step 2: 為欄位設置notifyPropertyChanged

這裡,老鐵需要謹記一點即可:

想讓誰更新,就給誰設置notifyPropertyChanged(BR.欄位名)。

而設置的規則,簡單如下:

例如,想為ClassBean中classNo設置更新,那麼只需要在setClassNo中添加notifyPropertyChanged(BR.classNo);即可,其他同理。

那麼,本小節演示所有欄位設置更新,那麼對應的代碼段如下:

   public void setClassNo(String classNo) {
       this.classNo = classNo;
       notifyPropertyChanged(BR.classNo);
   }
   public void setClassName(String className) {
       this.className = className;
       notifyPropertyChanged(BR.className);
   }
   public void setClassNum(String classNum) {
       this.classNum = classNum;
       notifyPropertyChanged(BR.classNum);
   }

而為了突出演示效果,這裡添加一個EditText,用於在用戶輸入數據時,動態修改實體,從而進行UI即時刷新。

同樣,也需要初始化以及設置事件,下面一起看看:

   private ActivityObservableBinding mBinding;
   private ClassBean mClassBean = new ClassBean("001", "100", "A1T105");
   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       mBinding = DataBindingUtil.setContentView(this, R.layout.activity_observable);
       mBinding.setClassX(mClassBean);
       mBinding.setPresenter(new Presenter());
   }
   public class Presenter {
       public void onTextChanged(CharSequence s, int start, int before, int count) {
           mClassBean.setClassNo("No:" + s);
           mClassBean.setClassNum("Num:" + s);
           mClassBean.setClassName("Name:" + s);
       }
   }

xml當中也只是簡單的調用事件以及賦值,簡單貼出部分代碼:

<EditText
   style="@style/titleStyle"
   android:onTextChanged="@{presenter.onTextChanged}" />
<TextView
   style="@style/contentStyle"
   android:text="展示數據更新-notifyPropertyChanged" />
<TextView
   style="@style/titleStyle"
   android:text="@{classX.classNo}" />
<TextView
   style="@style/titleStyle"
   android:text="@{classX.classNum}" />
<TextView
   style="@style/titleStyle"
   android:text="@{classX.className}" />

先來看一波效果:

有的小夥伴說了,這TMD太麻煩了,我實體類屬性欄位有很多腫麼辦?一個個添加嗎?

當然不。身為程序猿猿,能偷懶,當然不傻傻幹。瞧好吧您吶~

二、notifyChange方式更新全部數據

基於上節,本次單獨定義一個實體類,用於展示更新全部數據。

package com.hlq.databindingdemo.bean;
import android.databinding.BaseObservable;
import android.databinding.ObservableBoolean;

public class LoveBean extends BaseObservable {
   private String youSelf;
   private String mySelf;
   private ObservableBoolean isTrueLove = new ObservableBoolean();
   public LoveBean(String youSelf, String mySelf, boolean trueLove) {
       this.youSelf = youSelf;
       this.mySelf = mySelf;
       isTrueLove.set(trueLove);
   }
   public String getYouSelf() {
       return youSelf;
   }
   public void setYouSelf(String youSelf) {
       this.youSelf = youSelf;
   }
   public String getMySelf() {
       return mySelf;
   }
   public void setMySelf(String mySelf) {
       this.mySelf = mySelf;
   }
   public ObservableBoolean getIsTrueLove() {
       return isTrueLove;
   }
   public void setIsTrueLove(boolean isTrueLove) {
       this.isTrueLove.set(isTrueLove);
       notifyChange();
   }
}

這裡需要注意,只需要為一個單獨屬性欄位設置notifyChange即可實現所有數據均實現更新。

下面開始對應的初始化:

   private LoveBean mLoveBean = new LoveBean("Who are you", "H.L.Q.", true);
   ...
   mBinding.setLove(mLoveBean);
   ...
   mLoveBean.setYouSelf("Who are you?" + s);
   mLoveBean.setMySelf("H.L.Q." + s);
   mLoveBean.setIsTrueLove(!mLoveBean.getIsTrueLove().get());

一起來看看效果:

這裡LZ再囉嗦一句,倆者區別在於:

當然,Data Binding的神奇之處還有很多,比如,它為我們提供了對應的一系列ObservableField,那麼,下面,讓我們一起去看看吧~

三、ObservableField Study

簡單說一下ObservableField是什麼鬼:

首先,ObservableField是歸屬於Observable旗下,作用就是為了簡化操作,避免你寫多餘的get/set,當然嘍,優點並不止這些;

其次,Observable旗下包含了很多類似ObservableField的傢伙,例如:ObservableInt、ObservableBoolean等。

如何使用呢?你怎麼使用String、int等,就怎麼使用這個。說白了,就是一個配套的傢伙。

那麼接下來,簡單搞倆個Demo熟悉下使用:

Example One:先來個ObservableField練練手

Step 1: 定義實體類

import android.databinding.ObservableField;

public class MissBean {
   public final ObservableField<String> missWho = new ObservableField<>();
   public final ObservableField<String> missYou = new ObservableField<>();
}

Step 2: 布局引用

引入命名空間。

<data>
   <variable
       name="missBean"
       type="com.hlq.databindingdemo.bean.MissBean" />
</data>

設置對應值。

<TextView
   style="@style/titleStyle"
   android:text="@{missBean.missWho}" />
<TextView
   style="@style/titleStyle"
   android:text="@{missBean.missYou}" />

Step 3: Activity中初始化 - 賦值

mMissBean = new MissBean();
mMissBean.missWho.set("在思念誰?");
mMissBean.missYou.set("在思念你~");
mBinding.setMissBean(mMissBean);

Step 4: 查看效果

有的小夥伴說了,那我如果想取值呢?怎麼弄?

一張圖包教包會~ 再不會打死你~!

Example Two:再來個稍稍複雜的玩玩

Step 1: 定義我們實體類

package com.hlq.databindingdemo.bean;
import android.databinding.ObservableBoolean;
import android.databinding.ObservableField;
import android.databinding.ObservableInt;

public class ObservableFieldBean {
   public ObservableField<String> filedName = new ObservableField<>();
   public ObservableInt fileAge = new ObservableInt();
   public ObservableBoolean fileStore = new ObservableBoolean();
}

可以看到,我們這次不僅僅使用了ObservableField,還有ObservableInt以及ObservableBoolean,用法是不是很Easy?

Step 2: 引入命名空間,賦值

<data>
   <variable
       name="filedBean"
       type="com.hlq.databindingdemo.bean.ObservableFieldBean" />
</data>

接下來賦值:

<TextView
   style="@style/contentStyle"
   android:text="Observable Field" />
<TextView
   style="@style/titleStyle"
   android:text="@{filedBean.filedName}" />
<TextView
   style="@style/titleStyle"
   android:text='@{"年紀:"+filedBean.fileAge}' />
<TextView
   style="@style/titleStyle"
   android:text='@{"結果為:"+filedBean.fileStore}' />

Step 3: 初始化

mFiledBean = new ObservableFieldBean();
mFiledBean.filedName.set("賀大大");
mFiledBean.fileAge.set(22);
mFiledBean.fileStore.set(true);
mFieldBinding.setFiledBean(mFiledBean);

Step 4: 查看演示效果

四、ObservableArrayList Study

Step 1: 引入命名空間,聲明類型

<data>
   <import type="android.databinding.ObservableArrayList" />
   <variable
       name="loveList"
       type="ObservableArrayList&lt;String>" />
</data>

這裡需要注意,指定type時,ObservableArrayList類型裡面不能包含<,而是通過 < ; 代替

Step 2: 賦值

<TextView
   style="@style/contentStyle"
   android:text="ObservableArrayList Study" />
<TextView
   style="@style/titleStyle"
   android:text="@{loveList.get(0)}" />
<TextView
   style="@style/titleStyle"
   android:text="@{loveList.get(1)}" />

是不是很Easy,直接通過下標去訪問即可。

Step 3: 查看演示效果

五、ObservableMap Study

Step 1: 布局添加引用

<data>
   <import type="android.databinding.ObservableMap" />
   <variable
       name="loveMap"
       type="ObservableMap&lt;String,String>" />
</data>

Step 2: 賦值

<TextView
   style="@style/contentStyle"
   android:text="ObservableArrayMap Study" />
<TextView
   style="@style/titleStyle"
   android:text='@{loveMap["name"]}' />
<TextView
   style="@style/titleStyle"
   android:text='@{loveMap["age"]}' />

Step 3:  初始化

ObservableMap<String, String> testMap = new ObservableArrayMap<>();
testMap.put("name", "賀大寶,心情不美麗");
testMap.put("age", "22的年齡,嘖嘖");
mFieldBinding.setLoveMap(testMap);

Step 4:  查看效果演示圖

六、RecyclerView與DataBinding使用

目前的RecyclerView可謂火爆了半邊天,試問,現在還是誰沒用過?

先擼一波效果圖~

首先,我們來回顧下,之前我們最普通關於RecyclerView的使用:

定義布局文件,放置RecyclerView;

定義對應的item文件;

編寫對應的Java Bean以及Adapter,其中Adapter中需要單獨編寫ViewHolder類,且此類需繼承RecyclerView.ViewHolder。

大概簡單來講就是以上三個步驟,那麼我們根據以上三步驟並結合當前Data Binding去一步步學習掌握如何二者結合使用。

Step 1: 定義布局文件

這裡需要注意以下幾點:

上面說到,由於RecyclerView本身並不提供setData方式,所以我們需要自己造一個,那麼有的小夥伴就會問了,我之前沒使用Data Binding的時候,也不需要setData呀。其實這個東西大家可以簡單理解為,它就是一個橋接的作用,將傳遞過來的數據與RecyclerView綁定,也就是真正讓RecyclerView拿到傳遞的數據。 (當然,關於這塊如果有更好更通俗的解釋,歡迎拍磚~)

定義橋接類如下:

package com.hlq.databindingdemo.util;
import android.databinding.BindingAdapter;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import com.hlq.databindingdemo.adapter.ShowLoveHistoryAdapter;
import com.hlq.databindingdemo.bean.LoveBean;
import java.util.List;

public class BindUtils {
   @BindingAdapter("data")
   public static void setShowLoveHistoryData(RecyclerView recyclerView,
                                             List<LoveBean> loveList) {
       recyclerView.setLayoutManager(new LinearLayoutManager(recyclerView.getContext()));
       recyclerView.setAdapter(new ShowLoveHistoryAdapter(recyclerView.getContext(), loveList));
   }
}

而我們放置RecyclerView布局如下:

<?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>
       <import type="com.hlq.databindingdemo.bean.LoveBean" />
       <import type="android.databinding.ObservableArrayList" />
       <variable
           name="loveList"
           type="ObservableArrayList&lt;LoveBean>" />
   </data>
   <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       tools:context="com.hlq.databindingdemo.activity.RecyclerViewActivity">
       <android.support.v7.widget.RecyclerView
           android:id="@+id/showLove"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           app:data="@{loveList}" />
   </LinearLayout>
</layout>

Step 2: 定義對應的item文件

這裡我們簡單思考下:

既然是Adapter形式,那麼傳遞到Item中當然是一個實體類形式,我們只需要將每次遍歷得到的實體依次賦給item所需內容即可。

如演示圖所示,這裡為了方便就不單獨定義實體類了,直接使用原有的,如下:

<?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="love"
           type="com.hlq.databindingdemo.bean.LoveBean" />
   </data>
   <RelativeLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content">
       <ImageView
           android:id="@+id/icon"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:layout_margin="15dp"
           android:background="@drawable/ic_launcher_round" />
       <TextView
           style="@style/contentStyle"
           android:layout_centerVertical="true"
           android:layout_marginTop="15dp"
           android:layout_toRightOf="@id/icon"
           android:text="@{love.youSelf}"
           tools:text="姓名" />
       <View
           android:layout_width="match_parent"
           android:layout_height="1dp"
           android:layout_below="@id/icon"
           android:background="#fff" />
   </RelativeLayout>
</layout>

item效果如下:

Step 3: 編寫Adapter

package com.hlq.databindingdemo.adapter;
import android.content.Context;
import android.databinding.DataBindingUtil;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import com.hlq.databindingdemo.R;
import com.hlq.databindingdemo.bean.LoveBean;
import com.hlq.databindingdemo.databinding.ItemLoveHistoryShowBinding;
import com.hlq.databindingdemo.holder.ShowLoveHistoryHolder;
import java.util.List;

public class ShowLoveHistoryAdapter extends RecyclerView.Adapter<ShowLoveHistoryHolder> {
   private Context mContext;
   private List<LoveBean> mLoveList;
   public ShowLoveHistoryAdapter(Context mContext, List<LoveBean> mLoveList) {
       this.mContext = mContext;
       this.mLoveList = mLoveList;
   }
   @Override
   public ShowLoveHistoryHolder onCreateViewHolder(ViewGroup parent, int viewType) {
       ItemLoveHistoryShowBinding binding = DataBindingUtil.inflate(
               LayoutInflater.from(mContext),
               R.layout.item_love_history_show,
               parent, false);
       return new ShowLoveHistoryHolder(binding);
   }
   @Override
   public void onBindViewHolder(ShowLoveHistoryHolder holder, int position) {
       holder.getBinding().setLove(mLoveList.get(position));
       
       holder.getBinding().executePendingBindings();
   }
   @Override
   public int getItemCount() {
       return mLoveList == null ? 0 : mLoveList.size();
   }
}

這裡為了方便,單獨將ViewHolder抽取出來。

package com.hlq.databindingdemo.holder;
import android.support.v7.widget.RecyclerView;
import com.hlq.databindingdemo.databinding.ItemLoveHistoryShowBinding;

public class ShowLoveHistoryHolder extends RecyclerView.ViewHolder {
   private ItemLoveHistoryShowBinding binding;
   public ShowLoveHistoryHolder(ItemLoveHistoryShowBinding binding) {
       super(binding.getRoot());
       this.binding = binding;
   }
   public ItemLoveHistoryShowBinding getBinding() {
       return binding;
   }
   public void setBinding(ItemLoveHistoryShowBinding binding) {
       this.binding = binding;
   }
}

Step 4: 初始化

package com.hlq.databindingdemo.activity;
import android.databinding.DataBindingUtil;
import android.databinding.ObservableArrayList;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import com.hlq.databindingdemo.R;
import com.hlq.databindingdemo.bean.LoveBean;
import com.hlq.databindingdemo.databinding.ActivityRecyclerViewBinding;

public class RecyclerViewActivity extends AppCompatActivity {
   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       ActivityRecyclerViewBinding binding =
               DataBindingUtil.setContentView(this, R.layout.activity_recycler_view);
       ObservableArrayList<LoveBean> loveList = new ObservableArrayList<>();
       for (int i = 0; i < 30; i++) {
           loveList.add(new LoveBean("youSelf" + i, "mySelf" + i, true));
       }
       binding.setLoveList(loveList);
   }
}

嗯,小手一點,運行一波,走起~

七、老方式設置RecyclerView點擊事件

來來來,Come on,我們一起回顧下當年如何簡單有效實現RecyclerView並為其添加點擊事件:

Activity中擺放好RecyclerView;

初始化,編寫item以及對於Adapter、ViewHolder;

當然,不要忘記在adapter中設置事件,Activity中回調。

那麼基於以上路子,我們一塊快速簡單有效的擼一波有關結合Data Binding的用法吧~

Step 1:擺放RecyclerView

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools">
   <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:orientation="vertical"
       tools:context=".activity.NormalRecyclerViewActivity">
       <TextView
           style="@style/contentStyle"
           android:text="換種姿勢玩轉RecyclerView" />
       <android.support.v7.widget.RecyclerView
           android:id="@+id/showList"
           android:layout_width="match_parent"
           android:layout_height="match_parent" />
   </LinearLayout>
</layout>

Step 2:擺放Item_layout

這裡需要注意,因為我們是結合Data Binding,而真正落實到Item時,僅僅是一個Model,也就是我們最終的實體類。
So,在此,我們需要將我們的Model傳遞進去。

<?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.hlq.databindingdemo.bean.UserBean" />
   </data>
   <LinearLayout
       android:id="@+id/parent_list"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:orientation="vertical">
       <TextView
           android:id="@+id/item_list"
           style="@style/contentStyle"
           android:text="@{user.userName}"
           tools:text="item測試數據" />
       <View
           android:layout_width="match_parent"
           android:layout_height="2dp"
           android:background="#fff" />
   </LinearLayout>
</layout>

Step 3:編寫Adapter

這裡簡單總結下,看看我們的Adapter中需要落實些什麼鬼~!

嗯,基於以上三點,開始擼本次代碼:

package com.hlq.databindingdemo.adapter;
import android.content.Context;
import android.databinding.DataBindingUtil;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.hlq.databindingdemo.R;
import com.hlq.databindingdemo.bean.UserBean;
import com.hlq.databindingdemo.databinding.ItemShowListBinding;
import java.util.List;

public class ShowListAdapter extends RecyclerView.Adapter<ShowListAdapter.ViewHolder> {
   private Context mContext;
   private List<UserBean> mUserBeanList;
   private onItemClickListener mOnItemClickListener;
   private ItemShowListBinding mListBinding;
   public ShowListAdapter(Context context, List<UserBean> userBeanList) {
       this.mContext = context;
       this.mUserBeanList = userBeanList;
   }
   @Override
   public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
       mListBinding = DataBindingUtil.inflate(LayoutInflater.from(mContext), R.layout.item_show_list, parent, false);
       return new ViewHolder(mListBinding);
   }
   @Override
   public void onBindViewHolder(ViewHolder holder, final int position) {
       
       holder.mListBinding.setUser(mUserBeanList.get(position));
       
       holder.mListBinding.executePendingBindings();
       
       if (mOnItemClickListener != null) {
           holder.mListBinding.parentList.setOnClickListener(new View.OnClickListener() {
               @Override
               public void onClick(View v) {
                   mOnItemClickListener.onItemClickListener(mUserBeanList.get(position));
               }
           });
       }
   }
   @Override
   public int getItemCount() {
       return mUserBeanList.size();
   }
   class ViewHolder extends RecyclerView.ViewHolder {
       private ItemShowListBinding mListBinding;
       public ViewHolder(ItemShowListBinding listBinding) {
           super(listBinding.getRoot());
           this.mListBinding = listBinding;
       }
   }
   public void setOnItemClickListener(onItemClickListener onItemClickListener) {
       this.mOnItemClickListener = onItemClickListener;
   }
   public interface onItemClickListener {
       void onItemClickListener(UserBean userBean);
   }
}

Step 4:初始化RecyclerView、數據以及設置事件處理

   private ActivityNormalRecyclerViewBinding mNormalBinding;
   private ShowListAdapter mShowListAdapter;
   private List<UserBean> mShowList;
   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       mNormalBinding = DataBindingUtil.setContentView(this, R.layout.activity_normal_recycler_view);
       initData();
       initRecyclerViewSetting();
   }
   private void initData() {
       mShowList = new ArrayList<>();
       for (int i = 0; i < 30; i++) {
           mShowList.add(new UserBean("賀大大" + i));
       }
   }
   private void initRecyclerViewSetting() {
       mNormalBinding.showList.setLayoutManager(new LinearLayoutManager(this));
       mShowListAdapter = new ShowListAdapter(this, mShowList);
       mShowListAdapter.setOnItemClickListener(new ShowListAdapter.onItemClickListener() {
           @Override
           public void onItemClickListener(UserBean userBean) {
               Toast.makeText(NormalRecyclerViewActivity.this, "點擊了:" + userBean.getUserName(), Toast.LENGTH_SHORT).show();
           }
       });
       mNormalBinding.showList.setAdapter(mShowListAdapter);
   }

Step 5:運行一波,查看效果

嗯,簡單的玩完了,下面基於第六小節實現RecyclerView點擊~

八、來個裝B的方式設置RecyclerView點擊事件

既然本小節基於第六小節實現item點擊,那麼多餘的部分LZ這裡不再敘述,這裡著重講幾點思路:

當然為了便於接收者處理,這裡我們的事件直接傳遞Model,Adapter關鍵代碼如下:

   @Override
   public void onBindViewHolder(ShowLoveHistoryHolder holder, final int position) {
       holder.getBinding().setLove(mLoveList.get(position));
       
       holder.getBinding().executePendingBindings();
       
       if (mOnItemClickListener != null) {
           holder.getBinding().icon.setOnClickListener(new View.OnClickListener() {
               @Override
               public void onClick(View v) {
                   mOnItemClickListener.OnItemClickListener(mLoveList.get(position));
               }
           });
       }
   }
   public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
       this.mOnItemClickListener = onItemClickListener;
   }
   public interface OnItemClickListener {
       void OnItemClickListener(LoveBean loveBean);
   }

而對應的BindUtils中則只需要設置事件實例以及處理事件即可:

   @BindingAdapter("data")
   public static void setShowLoveHistoryData(final RecyclerView recyclerView,
                                             List<LoveBean> loveList) {
       recyclerView.setLayoutManager(new LinearLayoutManager(recyclerView.getContext()));
       ShowLoveHistoryAdapter adapter = new ShowLoveHistoryAdapter(recyclerView.getContext(), loveList);
       adapter.setOnItemClickListener(new ShowLoveHistoryAdapter.OnItemClickListener() {
           @Override
           public void OnItemClickListener(LoveBean loveBean) {
               Toast.makeText(recyclerView.getContext(), "點擊了:" + loveBean.getYouSelf(), Toast.LENGTH_SHORT).show();
           }
       });
       recyclerView.setAdapter(adapter);
   }

基於第六小節修改完畢,運行走一波~

九、當Data Binding遇到ImageView

在我們的上面有關RecyclerView時,大家注意到一個@BindingAdapter("data")麼?

這個東西是什麼?

簡單可以理解為:

@BindingAdapter()類似一個橋梁,主要負責數據到Data Binding層,同樣,牛掰的地方也在於,可以為你想使用的控制項硬生生加個特異功能~

好比我們的RecyclerView原本沒有接收數據的屬性,但是,薇薇改動後,就這麼神器的有了~~~

同理,依照上面如何為RecyclerView添加Data,下面先來擼一個有關ImageView的Util:

package com.hlq.databindingdemo.util;
import android.databinding.BindingAdapter;
import android.graphics.drawable.Drawable;
import android.widget.ImageView;
import com.bumptech.glide.Glide;

public class ImageUtils {
   @BindingAdapter("imageResource")
   public static void setImageResource(
           ImageView imageView,
           int imgID) {
       imageView.setImageResource(imgID);
   }
   @BindingAdapter("imageDrawable")
   public static void setImageDrawable(
           ImageView imageView,
           Drawable imgDrawable) {
       imageView.setImageDrawable(imgDrawable);
   }
   @BindingAdapter({"defaultImg", "loadingImg", "errorImg"})
   public static void setImageForGlide(
           ImageView imageView,
           Drawable defaultImg,
           String imageAddress,
           Drawable errorImg) {
       Glide.with(imageView.getContext())
               .load(imageAddress)
               .error(errorImg)
               .placeholder(defaultImg)
               .into(imageView);
   }
}

布局裡面就很easy咯(不過這裡要注意,調用者順序以及類型需要統一,不然真的就GG了~)

<?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="image"
           type="com.hlq.databindingdemo.bean.ImageBean" />
   </data>
   <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:gravity="center"
       android:orientation="vertical"
       tools:context=".activity.ImageViewActivity">
       <ImageView
           android:layout_width="80dp"
           android:layout_height="80dp"
           app:imageResource="@{image.imageResID}" />
       <ImageView
           android:layout_width="80dp"
           android:layout_height="80dp"
           android:layout_marginTop="15dp"
           app:imageDrawable="@{@drawable/hlq_gzh}" />
       <ImageView
           android:layout_width="80dp"
           android:layout_height="80dp"
           android:layout_marginTop="15dp"
           app:defaultImg="@{@drawable/hlq_gzh}"
           app:errorImg="@{@drawable/ic_launcher_round}"
           app:loadingImg="@{image.imgUrl}" />
   </LinearLayout>
</layout>

而對應Activity中則很easy,初始化即可:

mImageBinding = DataBindingUtil.setContentView(this, R.layout.activity_image_view);
ImageBean imageBean = new ImageBean();
imageBean.imageResID = R.drawable.ic_launcher_round;
imageBean.imgUrl = "http://d.hiphotos.baidu.com/image/pic/item/6159252dd42a2834171827b357b5c9ea14cebfcf.jpg";
mImageBinding.setImage(imageBean);

查看效果:

十、十全十美,進階收宮,來個註解完美告白

之前我們也多多少少使用了幾個項目中常用的註解,而本文最後,拓展幾個可能會用到的註解,來一個進階篇完美謝幕~

先來倆個惡搞薇薇的示例:

<?xml version="1.0" encoding="utf-8"?>
<layout>
   <data>
       <variable
           name="vv"
           type="com.hlq.databindingdemo.bean.VVBean" />
   </data>
   <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       xmlns:tools="http://schemas.android.com/tools"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:orientation="vertical"
       tools:context=".activity.WordActivity">
       <TextView
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:layout_marginTop="15dp"
           android:background="@{vv.vHeartBg ? @color/c_yellow : @color/c_while}"
           android:gravity="center"
           android:padding="15dp"
           android:text="VV內心顏色如同背景色"
           android:textColor="#000" />
       <TextView
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:layout_marginTop="15dp"
           android:background="@color/colorAccent"
           android:gravity="center"
           android:padding="15dp"
           android:text="@{vv.vDesc}"
           android:textColor="#000" />
   </LinearLayout>
</layout>

如下效果:

有的夥計說,你不怕薇薇懟你?

雞排我大哥~~~啦啦啦

扯犢子完成,最後為大家提溜過來@BindingMethods以及@BindingMethod這倆個註解,玩完睡覺,正好想想高級篇如何實現,不知不覺,一周又要過去了。。。

@BindingMethods以及@BindingMethod,這倆貨是一對兒,你別想著拆散人倆,小心AS不放過你,那麼具體他們使用以及場景又有哪兒些呢?

@BindingMethods,通常作為類的一個註解,它的作用,便是為其類或者實例添加新的技能;

@BindingMethod:苦逼執行者,旗下有三個小弟,如下:

type:給誰增加技能;

attribute :別人怎麼激活這個技能;

method:這個技能被激活後會什麼大招,enmmm,比如虐薇薇,嗯,對,虐薇薇~

總扯犢子不幹正事兒,小心被人說空有其表,華而不實:

首先,設置我們大招類:

package com.hlq.databindingdemo.weight;
import android.content.Context;
import android.databinding.BindingMethod;
import android.databinding.BindingMethods;
import android.support.annotation.Nullable;
import android.support.v7.widget.AppCompatTextView;
import android.util.AttributeSet;
import android.widget.Toast;

@BindingMethods(
       @BindingMethod(
               type = AppCompatTextView.class,
               attribute = "activation",
               method = "setActivation"
       )
)
public class VVBiuView extends AppCompatTextView {
   public VVBiuView(Context context, @Nullable AttributeSet attrs) {
       super(context, attrs);
   }
   
   public void setActivation(String msg) {
       Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT).show();
   }
}

大招蓄勢待發,下面開始布置環境(LZ這裡頑皮一波):

<?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="vv"
           type="com.hlq.databindingdemo.bean.VVBean" />
   </data>
   <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:orientation="vertical"
       tools:context=".activity.WordActivity">
       <com.hlq.databindingdemo.weight.VVBiuView
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:layout_marginTop="15dp"
           android:background="@color/colorPrimary"
           android:padding="15dp"
           android:text="我是隱藏大招~"
           app:activation="@{vv.vDesc}"/>
   </LinearLayout>
</layout>

有的夥伴說,哎那誰,你TMD的實體類哪兒去了?

MD,給你~!!!

package com.hlq.databindingdemo.bean;

public class VVBean {
   public boolean vHeartBg;
   public String vDesc;
   public VVBean(boolean vHeartBg, String vDesc) {
       this.vHeartBg = vHeartBg;
       this.vDesc = vDesc;
   }
}

emmmm,最後,簡單實例化一下:

mWordBind = DataBindingUtil.setContentView(this, R.layout.activity_word);
mWordBind.setVv(new VVBean(true, "程序猿,Oh,程序媛一枚,靈活的雙手編織動人的世界~"));

enmm,冒著被薇薇打死的風險擼完了,看下效果~

LZ比比會兒

有時候,總覺得自己很努力,但是未曾發現,那些比你優秀的人同樣在努力。

雞排,對技術的嚴謹,對成果的執著,對LZ這樣小白態度。。。等等,太多太多,心裡真的很佩服~

前行之楷模~!!!

薇薇,一個超級超級超級努力、拼的漂亮妹子,努力程度,讓我自愧不如。

。。。 。。。

身邊大佬默默努力的例子太多太多。。。

最後讓我們一起努力,也來個趕超雞排大大,迎娶薇薇大佬(開玩笑,開玩笑~~~)~

GitHub查看地址

https://github.com/HLQ-Struggle/DataBindingDemo

相關焦點

  • 從零開始的Android新項目8 - Data Binding高級篇
    原文:http://blog.zhaiyifan.cn/2016/07/06/android-new-project-from-0-p8/本文是MarkZhai同學系列文章的第8篇,剛剛完稿,此文承接 《從零開始的Android新項目7 - Data Binding入門篇》,繼續介紹Data Binding的進階內容,建議沒看過上篇的同學先前往閱讀,效果更佳,第7篇早前並沒有在我公眾號發布
  • 從零開始的Android新項目7 - Data Binding入門篇
    原文:http://blog.zhaiyifan.cn/2016/06/16/android-new-project-from-0-p7/本文是MarkZhai同學系列文章的第7篇,早前已發布,為配合今天推送的 《從零開始的Android新項目8 - Data Binding高級篇》,因此在這裡轉載給還沒看過的同學,讀完此文後,可以繼續閱讀公眾號推送的最新第8篇。
  • 【實戰】Android Data Binding從牴觸到愛不釋手
    文件夾,包含了layout的基本信息,導入的變量,View標籤中的表達式,標籤的位置索引等等,如下所示為data-binding-info/activity_detail3-layout.xml:(最終輸出到res/layout),即去掉根節點<layout>,去掉節點<data>,與不使用Data Binding時的layout相一致,例如data-binding-layout-out/activity_detail2.xml:
  • 如何進一步提升自己的英語閱讀能力?| 薦書 《大學英語閱讀進階》
    在《如何閱讀一本書》中,作者Adler把閱讀分為四個層級。
  • Pandas性能優化:進階篇
    3 進階 並行化處理並行化讀取數據在基礎篇講分塊讀取時,簡單提了一下並行化處理,這裡詳細說下代碼。第一種思路,分塊讀取,多進程處理。multiprocessing as mpimport timedef slow_func(s):    time.sleep(1)    return "done"with mp.Pool(mp.cpu_count()) as pool:    df['newcol'] = pool.map(slow_func, df['qid'])4 進階
  • AI瘋狂進階——激活函數篇
    本文作者專注於AI進階算法,正在推出AI瘋狂進階之基礎理論進階篇,如有興趣可持續關注我。 核心導讀: 1. 神經網絡激活函數的作用是什麼? 2. 如何評價激活函數的好壞? 3.
  • 朋友圈裝逼乾貨,攝影愛好者如何發高清圖片讓逼格提升
    還有一點就是,我們拍攝一輯照片往往不止9張照片想發,奈何朋友圈最多只能發9張圖片,假如你發兩次朋友圈一共18張,又顯得你對自己的作品特別執意,逼格一下就掉了,我們需要做的是要輕描淡寫的帶過一下,這樣的裝逼才高境界,而且你一次發這麼多張,即使是帥哥美女的照片也會審美疲勞,別說18張,就連9張也未必看完,你回想一下自己看別人朋友圈時,有多少次把9張圖片認真看完的
  • 測試員工作中提升逼格的一些單詞...
    AD:測試行業最牛的圈子,7年以上經驗才可加入點擊上面連結加群這裡收集了一些的90%程式設計師都喜歡會說的一些英文單詞,方便大家再跟研發同事交流過程中提升一些逼格兒。backward compatible 向後兼容、向下兼容base class 基類base type 基類型batch 批處理BCL (base class library)基類庫Bin Packing 裝箱問題binary 二進位binding
  • PS教程:「5分鐘調色法」提升照片逼格,讓你成為朋友圈最靚的仔!
    今天安利給你一個調色神器:PS中的Camera arw,只需5分鐘,讓你的照片逼格瞬間提高,成為朋友圈最靚的仔!掃碼觀看PS、AI、CDR等全套視頻是不是超簡單,速速get起來,朋友圈照片提升一個更多Camera arw調色教程請戳二維碼,進階調色大神
  • 【新教學上架】Unreal Engine 4遊戲特效實戰教學進階篇
    UnrealEngine4遊戲特效實戰教學進階篇本教學由DX_VFX老師錄製,通過8個遊戲特效實例帶大家學習常見的特效製作
  • 告別low生活 手機攝影APP快速提升逼格
    隨著手機攝影功能日益強大,APP變成了後期修圖必不可少的伴侶,今兒這篇文章就從幾張圖開始,推薦一些能幫你快速提升逼格的攝影APP。  先上來自朋友圈和微博的截圖,同樣是廈大芙蓉隧道,後者圖片拍的絲毫無感,除了文字,沒逼格可言。前者用了加過濾鏡的曬圖,有特點的塗鴉畫面選擇。
  • 如何用掃碼訂餐提升餐廳營收?
    今天我們就來了解一下掃碼點餐是如何解決餐飲行業痛點,提升店鋪營收的。01/點餐時間長,翻臺率低痛點:用餐高峰期,顧客排隊等位時間長,體驗感差,容易流失。解決辦法:通過掃碼點餐,顧客不用排隊手機就能下單,有效提高整體的翻臺率,提升餐廳營收。
  • 智能辦公桌 提升你的BOSS逼格
    佔南弦帶你進入逼格模式,溫暖你心!不知道大家有沒有注意到,66樓的總裁辦公桌上居然沒有電腦,那麼問題就來了,大BOSS是如何辦公的呢?快用你無敵的小腦袋想一想,哈哈,其實看到後面就揭曉了,原來你們的霸道總裁佔南弦平日的辦公全仰仗一張滿屏數據的智能桌。看到這裡有沒有感嘆,這部劇又提高了一個逼格,果然大集團裡的技術和設備都是一流的。
  • Matplotlib圖鑑|進階散點圖7-8
    大家好,從今天起,我們將開始更新Matplotlib進階散點圖圖鑑。本文將講解以下二個進階的散點圖繪製方法。進階散點圖-007下面我們就來講解如何繪製第一個進階散點圖,注意,代碼在以下環境全部通過測試:
  • 歐楷《結構》進階篇(2016新版)
    歐楷《基本筆畫》《結構》,是臺灣地區新北市國小的書法教材,由陳忠建老師講授與示範,這裡進行了重新編排整理,分為四篇推送:1、歐楷《基本筆畫》入門篇2、歐楷《基本筆畫》進階篇3、歐楷《結構》入門篇4、歐楷《結構》進階篇(本篇推送)這套課程十分適合初次接觸毛筆,剛剛開始學習歐陽詢楷書的朋友使用,也是中小學毛筆書法教學和書法培訓學校理想的參考資料。
  • 《跑跑卡丁車》如何進階漂移 進階漂移技巧介紹
    下面就是進階漂移技巧介紹,一起看看吧。 進階漂移技巧 高級技巧一 拖漂延續:也就是玩家在賽車持續保持拖漂的時候使用的技巧... 跑跑卡丁車遊戲中漂移是玩家都需要掌握的基礎技術,在遊戲中怎樣進階漂移?下面就是進階漂移技巧介紹,一起看看吧。
  • 鍵盤還能提升辦公室逼格?羅技K780圖賞
    鍵盤還能提升辦公室逼格?今天教大家,如何用一把高逼格的鍵盤同時兼顧幾臺設備從而提高辦公效率。
  • Keras使用進階(Ⅰ)
    例如在pyimagesearch的《multi-label-classification-with-keras》這篇文章中提出了一個衣服數據集,整個數據集有兩種屬性,一種是顏色(blue, red, black),另一種是衣服的類型(dress, jeans, shirt) 。
  • 惡搞漫畫:看擼胖如何酒桶變尿桶!
    惡搞漫畫:看擼胖如何酒桶變尿桶!擼胖是個酒鬼,每次一有錢就去鎮上買酒喝。又怕自己喝太快,不敢擺在家裡,就放在了屋子外面的小桌子上。好一點一點的慢慢品嘗。第二天一大早,擼胖饞酒喝饞得不行了,迫不及待地踏出了房門來到院子,結果看到了一個令人震驚的場景。擼胖的酒不知道被哪個小偷喝了四分之一。擼胖生氣了,就在酒瓶上貼了一張「不許偷酒」的紅色紙條。
  • 給語遲寶貝的繪本書單NO.2:進階篇
    ​寫了第一篇繪本推薦《給語遲寶貝的繪本書單NO.1:基礎篇》之後,馬上有家長想看第二篇。所以我果斷動筆寫了進階篇適合的年紀是3-6歲,當然也要看孩子的實際情況來。這篇裡推薦的繪本比基礎篇難度加大,我又加了一些自然科學、數學啟蒙方面的書,幫助孩子更好地理解。