近期本人一直在用Databinding,屬實好用,最近又發現有小夥伴封裝了recyclerView的Adapter,真是太給力了!拿過來與大家分享下。框架中提供了兩種適配器類型,single單一數據源和multi混合型數據源,針對不同的需求。一般情況下,我們常用的是single類型,因爲列表只定義一種類型數據源,但也不排除列表複雜,引入多種佈局,這時候我們可以用MultiTypeAdapter,具體使用後面介紹,我們先來看下封裝的Base adapter源碼:
public abstract class BaseViewAdapter<T> extends RecyclerView.Adapter<BindingViewHolder> { protected final LayoutInflater mLayoutInflater; protected List<T> mCollection; protected Presenter mPresenter; protected Decorator mDecorator; public interface Presenter { } public interface Decorator { void decorator(BindingViewHolder holder, int position, int viewType); } public BaseViewAdapter(Context context) { mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public void onBindViewHolder(BindingViewHolder holder, int position) { final Object item = mCollection.get(position); holder.getBinding().setVariable(BR.item, item); holder.getBinding().setVariable(BR.presenter, getPresenter()); holder.getBinding().executePendingBindings(); if (mDecorator != null) { mDecorator.decorator(holder, position, getItemViewType(position)); } } @Override public int getItemCount() { return mCollection.size(); } public void remove(int position) { mCollection.remove(position); notifyItemRemoved(position); } public void clear() { mCollection.clear(); notifyDataSetChanged(); } public void setDecorator(Decorator decorator) { mDecorator = decorator; } public void setPresenter(Presenter presenter) { mPresenter = presenter; } protected Presenter getPresenter() { return mPresenter; } }框架中定義了兩個接口,presenter響應事件,decorator裝飾器用來操作混合型適配器中的view及data。
base類繼承自RecyclerView.Adapter重寫了bindViewHolder方法,動態設置databingView 中的variable,注意的是框架中聲明瞭item,presenter兩個屬性,也就是說我們在使用時,recyclerView中的子佈局中數據源與響應事件必須爲item、presenter,如下:
<data> <variable name="item" type="com.wms.databinding.Student" /> <variable name="presenter" type="com.wms.databinding.RecyclerViewActivity.Presenter" /> </data>
引入jar:
dependencies {
compile 'com.github.markzhai:databinding-rv-adapter:1.0.1'
}
SingleTypeAdapter
SingleTypeAdapter與源生Adapter一樣,綁定item,添加數據源:
xml:
<android.support.v7.widget.RecyclerView android:id="@+id/rv_single" android:layout_width="match_parent" android:layout_height="match_parent" />item_xml:
<layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="item" type="com.wms.databinding.Student" /> <variable name="presenter" type="com.wms.databinding.RecyclerViewActivity.Presenter" /> </data> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@android:drawable/list_selector_background" android:onClick="@{()->presenter.onItemClick(item)}" android:padding="10dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text='@{"name:\t"+item.name}' /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:text='@{"age:\t"+item.age}' /> </RelativeLayout> </layout>然後Activity中去添加適配器:
singleTypeAdapter = new SingleTypeAdapter(this, R.layout.item_rv); //設置適配器監聽 singleTypeAdapter.setPresenter(new Presenter()); //設置數據源 clear and add singleTypeAdapter.set(getData()); binding.rvSingle.setLayoutManager(new LinearLayoutManager(this)); binding.rvSingle.setAdapter(singleTypeAdapter);
監聽實現BaseViewAdapter中的Presenter,然後自定義方法:
public class Presenter implements BaseViewAdapter.Presenter { public void onItemClick(Student item) { Toast.makeText(RecyclerViewActivity.this, item.getName() + "---" + item.getAge(), Toast.LENGTH_SHORT).show(); } }
SingleTypeAdapter源碼中定義了幾個方法用來設置數據源,set方法清空list並添加:
public void set(List<T> viewModels) { mCollection.clear(); addAll(viewModels); }addAll在list中add數據:
public void addAll(List<T> viewModels) { mCollection.addAll(viewModels); notifyDataSetChanged(); }
MultiTypeAdapter
定製了混合型數據源adapter,可以加載不同的子佈局,加載不同數據源。
列表子佈局引入了兩個佈局,第一個佈局是single中的item,第二個佈局新增了一個title佈局:
<layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="presenter" type="com.wms.databinding.RecyclerViewActivity.Presenter" /> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:orientation="vertical"> <TextView android:id="@+id/title" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:padding="10dp" android:textColor="@android:color/holo_red_dark" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick='@{()->presenter.onBtnTitle("Title Msg")}' /> </LinearLayout> </layout>
multiTypeAdapter = new MultiTypeAdapter(this); //設置混合佈局樣式 multiTypeAdapter.addViewTypeToLayoutMap(TITLE_TYPE, R.layout.item_multi_title); multiTypeAdapter.addViewTypeToLayoutMap(ITEM_TYPE, R.layout.item_rv); //設置適配器監聽 multiTypeAdapter.setPresenter(new Presenter()); //設置裝飾器 multiTypeAdapter.setDecorator(new TitleDecorator()); //設置混合數據源 multiTypeAdapter.add(null, TITLE_TYPE); multiTypeAdapter.addAll(getData(), ITEM_TYPE); binding.rvMulti.setLayoutManager(new LinearLayoutManager(this)); binding.rvMulti.setAdapter(multiTypeAdapter);addViewTypeLayoutMap(int type, int res) 添加布局類型及佈局資源,add(object data,int type) 向指定佈局中添加數據。其中添加了decorator用來操作混合佈局中的指定佈局,我demo中是對title佈局進行操作:
public class TitleDecorator implements BaseViewAdapter.Decorator { @Override public void decorator(BindingViewHolder holder, int position, int viewType) { if (TITLE_TYPE == viewType) { ItemMultiTitleBinding titleBinding = (ItemMultiTitleBinding) holder.getBinding(); titleBinding.title.setText("This is multi title"); } } }運行如下:
是不是感覺很好用呢,Demo地址。