前言
早期文章 荡含, 如今搬運(yùn)過來 释液, RecyclerView用法相信都會误债,這里主要介紹一下簡單的封裝寝蹈。
不管我們是在使用早期的ListView
還是使用強(qiáng)大的RecyclerView
,我們都需要去實(shí)現(xiàn)其控件的Adapter 箫老,將數(shù)據(jù)與控件綁定起來 耍鬓。不管是ListViewAdapter
還是RecyclerViewAdapter
牲蜀,都需要我們實(shí)現(xiàn)大量的方法 ,重復(fù)的去編寫相同的操作 涣达,為了減少不必要的編碼 度苔,就需要將Adapter的共性抽取出來 寇窑,做成一個(gè)通用的Adapter ,以后需要實(shí)現(xiàn)Adapter 完残,只需要繼承我們自己寫的Adapter就OK了 横漏。
分析
不管是我們的ListViewAdapter還是RecyclerViewAdapter 缎浇,其主要有兩點(diǎn) :
第一、 外界提供給我們的數(shù)據(jù)源 二蓝, 這個(gè)是變化的 刊愚。
第二踩验、 外界提供給我們的布局文件資源(也可拓展為布局View) 箕憾, 這個(gè)也是變化,需要傳遞的參數(shù)
另 : RecyclerView需要我們自己實(shí)現(xiàn)Item的各種事件
如果布局中需要Context 钠龙,也可以作為參數(shù)傳入 碴里,創(chuàng)建多個(gè)構(gòu)造函數(shù)
編寫 :
要封裝RecyclerView.Adapter畅买,就需要搞清楚,RecyclerViewAdapter主要實(shí)現(xiàn)三個(gè)方法 帝火,onCreateViewHolder
、onBindViewHolder
蠢壹、getItemCount
九巡,還有一個(gè)ViewHolder類 。我們來分析分析 疏日, 這幾個(gè)方法和類 撒汉。
onCreateViewHolder
主要構(gòu)件RecyclerView
每個(gè)Item布局對象 睬辐,與ViewHolder關(guān)聯(lián) 溯饵,達(dá)到復(fù)用視圖的效果,并傳遞給 onBindViewHolder
隘谣,因?yàn)槲覀兊牟季謱ο蠖际荲iew 洪橘, 所以這個(gè)地方 棵帽, 我們可以根據(jù)傳遞進(jìn)來的資源文件infalter成一個(gè)View 逗概,亦或是傳進(jìn)來的View逾苫,再與ViewHolder關(guān)聯(lián) 铅搓, 此處我們就可以對外屏蔽掉了 搀捷。
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
View view = LayoutInflater.from(parent.getContext()).inflate(mItemLayoutRes, parent,
false);
ViewHolder viewHolder = new ViewHolder(view);
// 初始化Item事件監(jiān)聽
initOnItemListener(viewHolder);
return viewHolder;
}
onBindViewHolder
主要講數(shù)據(jù)與ViewHolder里面的控件相關(guān)聯(lián) ,因?yàn)槲乙獙?shí)現(xiàn)不同RecyclerView Item的數(shù)據(jù)顯示 怀偷,所以這個(gè)地方不能寫死 椎工,需要我們根據(jù)情況 蜀踏,將數(shù)據(jù)綁定到不同的控件上面 , 這里需要抽象方法傳遞出來數(shù)據(jù) 颅痊, 讓繼承我們的Adapter做操作
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
Object o = mItems.get(position);
convertView((ViewHolder) holder,o);
}
getItemCount
@Override
public int getItemCount()
{
return mItems.size();
}
返回我們的Item總條數(shù)
ViewHolder
將ViewHolder類抽取出來八千,主要是為了更加方便的進(jìn)行View組件的操作恋捆,這個(gè)類 重绷,主要是為我們的控件復(fù)用服務(wù) ,因?yàn)樵贏dapter每個(gè)Item與ViewHolder關(guān)聯(lián) 愤钾,所以在此類中 能颁, 我們可以做一些獲取控件的簡便操作 。
private View mConvertView;
private SparseArray<View> mViews;
public ViewHolder(View itemView)
{
super(itemView);
mViews = new SparseArray<>() ;
mConvertView = itemView ;
}
/**
* 根據(jù)資源獲取View對象
* @param res
* @param <T>
* @return
*/
public <T extends View> T getView(@IdRes int res) {
View view = mViews.get(res);
if (view == null) {
view = mConvertView.findViewById(res) ;
mViews.put(res,view);
}
return (T) view;
}
完整Adapter代碼
/**
* Created by Zeno on 2016/6/8.
*
* 簡介 :
* 抽象類的抽取 ,主要是抽取一些有共性的方法和參數(shù) 敌土。
*
* 分析:
* 不管是ListView還是RecyclerView 兴枯,主要有兩個(gè)點(diǎn)需要實(shí)現(xiàn):
* 第一 :外界提供的數(shù)據(jù)源
* 第二 :外界提供的布局
* 這兩個(gè)點(diǎn)是明確從外部傳入的 财剖,所以首先這兩個(gè)點(diǎn)不能固定 悠夯,需要作為參數(shù)從外部傳入
* 如果有一些資源需要用到上下文 ,還需要傳入Context
*
*
*/
public abstract class SimpleBaseRecyclerAdapter extends RecyclerView.Adapter
{
// each item layout res
private int mItemLayoutRes;
// total item data set
private List<?> mItems;
private ItemClickListener mItemClickListener ;
private ItemLongClickListnener mItemLongClickListnener ;
public SimpleBaseRecyclerAdapter(@LayoutRes int mItemLayoutRes, List<?> items)
{
this.mItemLayoutRes = mItemLayoutRes;
// 如果沒有傳入的數(shù)據(jù) 峰伙,則自動創(chuàng)建一個(gè)空的集合 疗疟,防止報(bào)空指針
this.mItems = items ==null ? new ArrayList<>() : items;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
View view = LayoutInflater.from(parent.getContext()).inflate(mItemLayoutRes, parent,
false);
ViewHolder viewHolder = new ViewHolder(view);
// 初始化Item事件監(jiān)聽
initOnItemListener(viewHolder);
return viewHolder;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
Object o = mItems.get(position);
convertView((ViewHolder) holder,o);
}
@Override
public int getItemCount()
{
return mItems.size();
}
public abstract void convertView(ViewHolder viewHolder, Object itemObj) ;
/**
* init set item view listener
* @param holder
*/
private void initOnItemListener(final RecyclerView.ViewHolder holder) {
if (mItemClickListener != null) {
holder.itemView.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
Object o = mItems.get(holder.getLayoutPosition());
mItemClickListener.onItemClick(v,o ,holder.getLayoutPosition());
}
});
}
if (mItemLongClickListnener != null) {
holder.itemView.setOnLongClickListener(new View.OnLongClickListener()
{
@Override
public boolean onLongClick(View v)
{
Object o = mItems.get(holder.getLayoutPosition());
mItemLongClickListnener.onItemLongClick(v,o,holder.getLayoutPosition());
return true;
}
});
}
}
/**
* set item view click
* @param listener
*/
public void setOnItemClickListener(ItemClickListener listener) {
mItemClickListener = listener ;
}
/**
* set item view long click
* @param listener
*/
public void setOnItemLongClickListener(ItemLongClickListnener listener) {
mItemLongClickListnener = listener ;
}
public interface ItemClickListener {
void onItemClick(View view ,Object itemObj , int position) ;
}
public interface ItemLongClickListnener {
void onItemLongClick(View view ,Object itemObj, int position) ;
}
}
完整ViewHolder代碼
/**
* Created by Zeno on 2016/6/8.
*
* ViewHolder主要是做一些與控件布局有關(guān)的操作 ,所有我們可以在這邊簡化一下獲取控件對象的代碼
*/
public class ViewHolder extends RecyclerView.ViewHolder
{
private View mConvertView;
private SparseArray<View> mViews;
public ViewHolder(View itemView)
{
super(itemView);
mViews = new SparseArray<>() ;
mConvertView = itemView ;
}
/**
* 根據(jù)資源獲取View對象
* @param res
* @param <T>
* @return
*/
public <T extends View> T getView(@IdRes int res) {
View view = mViews.get(res);
if (view == null) {
view = mConvertView.findViewById(res) ;
mViews.put(res,view);
}
return (T) view;
}
/**
* 提供TextView和Button設(shè)置文本簡化操作
* @param idRes
* @param charSequence
* @return
*/
public ViewHolder setText(@IdRes int idRes , CharSequence charSequence) {
View view = getView(idRes);
if (view instanceof TextView) {
((TextView)view).setText(charSequence);
}else if (view instanceof Button) {
((Button)view).setText(charSequence);
}
return this ;
}
/**
* 提供TextView和Button設(shè)置文本顏色簡化操作
* @param idRes
* @param color
* @return
*/
public ViewHolder setTextColor(@IdRes int idRes , int color) {
View view = getView(idRes);
if (view instanceof TextView) {
((TextView)view).setTextColor(color);
}else if (view instanceof Button) {
((Button)view).setTextColor(color);
}
return this ;
}
/**
* 設(shè)置指定ViewId的背景顏色
* @param idRes
* @param color
* @return
*/
public ViewHolder setBackgroundColor(@IdRes int idRes , int color) {
View view = getView(idRes);
view.setBackgroundColor(color);
return this;
}
/**
* 設(shè)置ImageView顯示圖片
* @param idRes
* @param res
* @return
*/
public ViewHolder setImageResoruce(@IdRes int idRes , @DrawableRes int res) {
View view = getView(idRes);
if (view instanceof ImageView) {
((ImageView)view).setImageResource(res);
}
return this ;
}
/**
* 設(shè)置指定控件ID的點(diǎn)擊事件
* @param idRes
* @param listener
* @return
*/
public ViewHolder setOnClickListener(@IdRes int idRes , View.OnClickListener listener) {
View view = getView(idRes);
view.setOnClickListener(listener);
return this;
}
/**
* 設(shè)置指定控件ID的長按事件
* @param idRes
* @param listener
* @return
*/
public ViewHolder setOnLongClickListener(@IdRes int idRes , View.OnLongClickListener listener) {
View view = getView(idRes);
view.setOnLongClickListener(listener);
return this;
}
/**
* 設(shè)置指定控件的TAG
* @param idRes
* @param tag
* @return
*/
public ViewHolder setTag(@IdRes int idRes , Object tag) {
View view = getView(idRes);
view.setTag(tag);
return this;
}
/**
* 獲取指定控件的TAG
* @param idRes
* @return
*/
public Object getTag(@IdRes int idRes) {
View view = getView(idRes);
return view.getTag() ;
}
}