天天看點

RecyclerView通用的Adapter封裝三、代碼四、執行個體

一、需求分析

        當我們使用RecyclerView的時候,基本都需要寫一個擴充卡繼承RecyclerAdapter,其中有很多需要重寫的方法,并且這部分代碼也都是重複的,還有ViewHolder的重用代碼,每次都要寫一遍的話很繁瑣,是以我們可以把這部分代碼全部封裝出來,然後子類隻需要處理關鍵性的代碼就行。

二、功能

  • item 的點選事件回調
  • item 的長按時間回調
  • ViewHolder 的封裝
  • 大量重複的父類方法實作,子類不再需要實作它們不同的部分代碼

三、代碼

下面代碼封裝了RecyclerAdapter,同時有一個通用性的ViewHolder,這個ViewHolder類也可以作為一個公用的類來使用。

代碼裡面添加了一個item的點選事件回調,還有一個item的長按事件回調。

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
 
import java.util.List;
 
public abstract class MyRecyclerAdapter<T> extends RecyclerView.Adapter<MyRecyclerAdapter.ViewHolder> {
 
    protected Context mContext;
    protected int mLayoutId;
    protected List<T> mList;
 
    private OnItemClickListener mOnItemClickListener;
    private OnItemLongClickListener mOnItemLongClickListener;
 
    public MyRecyclerAdapter() {}
 
    public MyRecyclerAdapter(Context context, List<T> list, int layoutId) {
        mContext = context;
        mList = list;
        mLayoutId = layoutId;
    }
 
    @Override
    public ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
        ViewHolder viewHolder = ViewHolder.getInstance(mContext, mLayoutId, parent);
        return viewHolder;
    }
 
    @Override
    public void onBindViewHolder(final ViewHolder holder, int position) {
        if (mList.size() > 0)
            convert(holder, mList.get(position), position);
        if (mOnItemClickListener != null) {
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    int position = holder.getLayoutPosition();
                    mOnItemClickListener.onItemClick(holder.itemView, position);
                }
            });
        }
        if (mOnItemLongClickListener != null) {
            holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    int position = holder.getLayoutPosition();
                    mOnItemLongClickListener.onItemLongClick(holder.itemView, position);
                    return true; // 傳回true 表示消耗了事件 事件不會繼續傳遞
                }
            });
        }
    }
 
    public abstract void convert(ViewHolder holder, T t, int position);
 
    @Override
    public int getItemCount() {
        return mList.size();
    }
 
    public void setOnItemClickListener(OnItemClickListener mOnItemClickListener) {
        this.mOnItemClickListener = mOnItemClickListener;
    }
 
    public void setOnItemLongClickListener(OnItemLongClickListener mOnItemLongClickListener) {
        this.mOnItemLongClickListener = mOnItemLongClickListener;
    }
 
    public interface OnItemClickListener {
        void onItemClick(View view, int position);
    }
 
    public interface OnItemLongClickListener {
        void onItemLongClick(View view, int position);
    }
 
    protected static class ViewHolder extends RecyclerView.ViewHolder {
 
        private SparseArray<View> mViews;
        private View mConvertView;
 
        public ViewHolder(View itemView) {
            super(itemView);
            mConvertView = itemView;
            mViews = new SparseArray<>();
        }
 
        public static ViewHolder getInstance(Context context, int layoutId, ViewGroup parent) {
            View itemView = LayoutInflater.from(context).inflate(layoutId, parent, false);
            ViewHolder holder = new ViewHolder(itemView);
            return holder;
        }
 
        public <T extends View> T getView(int viewId) {
            View view = mViews.get(viewId);
            if (view == null) {
                view = mConvertView.findViewById(viewId);
                mViews.put(viewId, view);
            }
            return (T) view;
        }
 
    }
 
}
           

四、執行個體

下面這個執行個體是一個存在多個 type 的執行個體

import android.content.Context;
import android.graphics.Color;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
 
import com.afei.R;
import com.afei.bean.TargetLibWrapper;
 
import java.util.List;
 
public class TargetLibCollapseAdapter extends MyRecyclerAdapter<TargetLibWrapper> {
 
    private static final int TYPE_CATEGORY = 0;
    private static final int TYPE_ITEM = 1;
 
    private int categoryLayoutId;
    private int itemLayoutId;
    private int mDividePos;
 
    public TargetLibCollapseAdapter(Context context, List<TargetLibWrapper> list) {
        mContext = context;
        mList = list;
        categoryLayoutId = R.layout.target_lib_category_layout;
        itemLayoutId = R.layout.target_lib_item_collapse_layout;
    }
 
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        ViewHolder holder;
        if (viewType == TYPE_CATEGORY) {
            holder = ViewHolder.getInstance(mContext, categoryLayoutId, parent);
        } else {
            holder = ViewHolder.getInstance(mContext, itemLayoutId, parent);
        }
        return holder;
    }
 
    @Override
    public void convert(ViewHolder holder, TargetLibWrapper wrapper, final int position) {
        if (getItemViewType(position) == TYPE_CATEGORY) {
            ImageView searchIv = holder.getView(R.id.is_search_iv);
            TextView searchTv = holder.getView(R.id.is_search_tv);
            searchIv.setImageResource(wrapper.isSearch() ? R.mipmap.ic_search_true : R.mipmap.ic_search_false);
            int color = wrapper.isSearch() ? mContext.getResources().getColor(R.color.targetLibItemChecked) : Color
                    .BLACK;
            searchTv.setTextColor(color);
            searchTv.setText(wrapper.getCategoryName());
        } else {
            ImageView statusIv = holder.getView(R.id.target_lib_status_iv);
            ImageView folderIv = holder.getView(R.id.target_lib_folder_iv);
            TextView nameTv = holder.getView(R.id.target_lib_name_tv);
            statusIv.setImageResource(wrapper.isSearch() ? R.mipmap.ic_delete : R.mipmap.ic_add);
            folderIv.setImageResource(wrapper.isSearch() ? R.mipmap.ic_folder_checked : R.mipmap.ic_folder_unchecked);
            nameTv.setText(wrapper.getTargetLibEntity().getName());
            statusIv.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    move(position);
                }
            });
        }
    }
 
    @Override
    public int getItemViewType(int position) {
        if (mList.get(position).isCategory()) {
            if (position != 0) {
                mDividePos = position;
            }
            return TYPE_CATEGORY;
        }
        return TYPE_ITEM;
    }
 
    private void move(int position) {
        TargetLibWrapper targetLib = mList.get(position);
        if (targetLib.isSearch()) {
            targetLib.setSearch(false);
            mList.remove(position);
            mList.add(mDividePos, targetLib);
        } else {
            targetLib.setSearch(true);
            mList.remove(position);
            mList.add(1, targetLib);
        }
        notifyDataSetChanged();
    }
 
}