Android 探究onCreateViewHolder和onBindViewHolder两者关系和调用次数


    As we all know-众所周知,RecycleView 在展示数据列表的页面替换Listview的趋势已然出现,现在网络上关于它的资料也是铺天盖地,我就不再介绍如何使用了。但是,我对RecycleView的Adapter还是比较感兴趣的,因为懂得了Adapter,对于RecycleView的扩展及优化会很有帮助。这篇文章,先了解一下 onCreateViewHolder调用次数和 onBindViewHolder 之间的暧昧关系。


添加依赖

com.android.support:appcompat-v7:26.1.0
com.android.support:recyclerview-v7:26.1.0

(提示:根据自己android.support 版本去调整recycleView依赖版本)


上代码嘞!


RecyclerViewAdapter.class :继承RecyclerView.Adapter后,会重写三个方法:

public class RecycleViewAdapter extends RecyclerView.Adapter {

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return null;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

    }

    @Override
    public int getItemCount() {
        return 0;
    }
}
onCreateViewHolder()方法,负责承载每个子项的布局。它有两个参数,其中一个是 int viewType;
onBindViewHolder()方法,负责将每个子项holder绑定数据。俩参数分别是RecyclerView.ViewHolder holder, int position;
by the way-顺便说下,该类继承的RecyclerView.Adapter。其实可以加泛型ViewHolder,如下:
public class RecycleViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return null;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

    }

    @Override
    public int getItemCount() {
        return 0;
    }
}


布局文件

item_layout.xml 。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/txt"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:text="xxx"/>

</LinearLayout>

Usually-通常情况下,我们会define一个ViewHolder类喔,这样方便绑定数据和扩展。

 public Context mContext;
    static class ViewHolde extends RecyclerView.ViewHolder {

        TextView txt;
        public ViewHolde(View itemView) {
            super(itemView);
            txt = itemView.findViewById(R.id.txt);
        }
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View item = LayoutInflater.from(mContext).inflate(R.layout.item_layout , parent ,false);
        return new RecyclerAdapter.ViewHolde(item);
    }


绑定数据

data.class 实体类。(动手敲代码的复制即可)
public class data {
    /**
     * 名字
     */
    private String name;
    /**
     * 子项类型
     * 1: 标题
     * 2:普通
     */
    private int type;
    public data(String name, int type) {
        this.name = name;
        this.type = type;
    }
    public String getName() {
        return name;
    }
    
    public int getType() {
        return type;
    }
    /**
     * 存储的数据列表
     */
    private static List<data> mDataList;
    public static List<data> getDataList() {
        if (mDataList == null){
            mDataList = new ArrayList<>();

            data bean1 = new data("热销推荐",1);
            mDataList.add(bean1);
            mDataList.addAll(foods("热销零食"));

            data bean2 = new data("菜品",1);
            mDataList.add(bean2);
            mDataList.addAll(foods("小菜一碟"));

            data bean3 = new data("主食",1);
            mDataList.add(bean3);
            mDataList.addAll(foods("馒头,嗷~"));

            data bean4 = new data("饮料",1);
            mDataList.add(bean4);
            mDataList.addAll(foods("啤酒饮料矿泉水"));

        }
        return mDataList;
    }
    /**
     * 循环存储食物名字
     * @param foodName
     * @return
     */
    private static List<data> foods(String foodName){
        List<data> foods =new ArrayList<>();
        data food = null;
        for (int i = 0 ; i < 10 ; i++){
            food = new data(foodName+"("+i+")",2);
            foods.add(food);
        }
        return foods;
    }
}
索性,我就把Adapter里的全部代码贴出来咯!其实代码很简单,如下:
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    /**
     * context
     */
    public Context mContext;

    /**
     * 集合
     */
    public List<data> mDatas = new ArrayList<>();
    /**
     * data
     */
    public data mData;

    public RecyclerAdapter(Context mContext, List<data> mDatas) {
        this.mContext = mContext;
        this.mDatas = mDatas;
    }

    static class ViewHolde extends RecyclerView.ViewHolder {

        TextView txt;
        public ViewHolde(View itemView) {
            super(itemView);
            txt = itemView.findViewById(R.id.txt);
        }
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View item = LayoutInflater.from(mContext).inflate(R.layout.item_layout , parent ,false);
        Log.d("aaa","onCreateViewHolder————"+viewType);
        if (viewType == 1){//标题
            item.setTag(true);
        }else{
            item.setTag(false);
        }
        return new ViewHolde(item);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (holder instanceof  ViewHolde){
            mData =mDatas.get(position);
           ((ViewHolde) holder).txt.setText(mData.getName());
            Log.d("aaa","onBindViewHolder————"+mData.getName());
           if (mData.getType() == 1){
               ((ViewHolde) holder).txt .setTextColor(mContext.getColor(R.color.colorAccent));
               ((ViewHolde) holder).txt .setBackgroundColor(mContext.getColor(R.color.colorPrimary));
               ((ViewHolde) holder).txt .setTextSize(20);
           }
        }
    }

    @Override
    public int getItemViewType(int position) {
        Log.d("aaa","getItemViewType————"+ mDatas.get(position).getType());
        return mDatas.get(position).getType();
    }
   
    @Override
    public int getItemCount() {
        return mDatas.size();
    }
}

运行结果

public class MainActivity extends AppCompatActivity {

    RecyclerView mRecyclerView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mRecyclerView  =findViewById(R.id.recyclelist);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        mRecyclerView.setAdapter(new RecyclerAdapter(this, data.getDataList()));
    }
}
好了,我们先运行看效果吧。
估计,看官们看代码也已经不耐烦了吧?  
看完效果,我们接着说。


Log日志分析

其实,我们已经知道答案了,因为最后我把dapter代码贴出后,大家可能没注意,我在关键地方都标有log输出。

扫描二维码关注公众号,回复: 2017854 查看本文章

打印如下:  

04-26 16:07:45.535 D/aaa: getItemViewType————1
04-26 16:07:45.540  D/aaa: onCreateViewHolder————1
04-26 16:07:45.541  D/aaa: onBindViewHolder————热销推荐
04-26 16:07:45.544  D/aaa: getItemViewType————2
04-26 16:07:45.547  D/aaa: onCreateViewHolder————2
04-26 16:07:45.547  D/aaa: onBindViewHolder————热销零食(0)
04-26 16:07:45.549  D/aaa: getItemViewType————2
04-26 16:07:45.551  D/aaa: onCreateViewHolder————2
04-26 16:07:45.552  D/aaa: onBindViewHolder————热销零食(1)
04-26 16:07:45.553  D/aaa: getItemViewType————2
04-26 16:07:45.556  D/aaa: onCreateViewHolder————2
04-26 16:07:45.556  D/aaa: onBindViewHolder————热销零食(2)
04-26 16:07:45.557  D/aaa: getItemViewType————2
04-26 16:07:45.560  D/aaa: onCreateViewHolder————2
04-26 16:07:45.560  D/aaa: onBindViewHolder————热销零食(3)
04-26 16:07:45.561  D/aaa: getItemViewType————2
04-26 16:07:45.563  D/aaa: onCreateViewHolder————2
04-26 16:07:45.564  D/aaa: onBindViewHolder————热销零食(4)
04-26 16:07:45.565  D/aaa: getItemViewType————2
04-26 16:07:45.568  D/aaa: onCreateViewHolder————2
04-26 16:07:45.568  D/aaa: onBindViewHolder————热销零食(5)
04-26 16:07:45.569  D/aaa: getItemViewType————2
04-26 16:07:45.572  D/aaa: onCreateViewHolder————2
04-26 16:07:45.572  D/aaa: onBindViewHolder————热销零食(6)
04-26 16:07:45.574  D/aaa: getItemViewType————2
04-26 16:07:45.576  D/aaa: onCreateViewHolder————2
04-26 16:07:45.576  D/aaa: onBindViewHolder————热销零食(7)
04-26 16:07:45.577  D/aaa: getItemViewType————2
04-26 16:07:45.579  D/aaa: onCreateViewHolder————2
04-26 16:07:45.579  D/aaa: onBindViewHolder————热销零食(8)
04-26 16:07:45.580  D/aaa: getItemViewType————2
04-26 16:07:45.582  D/aaa: onCreateViewHolder————2
04-26 16:07:45.582  D/aaa: onBindViewHolder————热销零食(9)
04-26 16:07:45.584  D/aaa: getItemViewType————1
04-26 16:07:45.586  D/aaa: onCreateViewHolder————1
04-26 16:07:45.587  D/aaa: onBindViewHolder————菜品
04-26 16:07:45.589  D/aaa: getItemViewType————2
04-26 16:07:45.591  D/aaa: onCreateViewHolder————2
04-26 16:07:45.592  D/aaa: onBindViewHolder————小菜一碟(0)
04-26 16:07:45.593  D/aaa: getItemViewType————2
04-26 16:07:45.596  D/aaa: onCreateViewHolder————2
04-26 16:07:45.596  D/aaa: onBindViewHolder————小菜一碟(1)
04-26 16:07:45.597  D/aaa: getItemViewType————2
04-26 16:07:45.599  D/aaa: onCreateViewHolder————2
04-26 16:07:45.599  D/aaa: onBindViewHolder————小菜一碟(2)
04-26 16:07:45.601  D/aaa: getItemViewType————2
04-26 16:07:45.603  D/aaa: onCreateViewHolder————2
04-26 16:07:45.603  D/aaa: onBindViewHolder————小菜一碟(3)

很简单,我来分析一波~~ ^_^

首先,日志只打印出页面展示出的所有子项。说明啥?嗯,答案跟你想的一样。

其次,总结方法执行规律: getItemViewType   》 onCreateViewHolder  》 onBindViewHolder

最后,我们居然不小心知道了onCreateViewHolder 和 onBindViewHolder调用次数是保持一致的。它们为每个子项都执行了一次


结尾,送菊花。

最后说一句话,下面一篇文章是把这个案例升级,实现可以吸附在顶部的列表小标题。欢迎各位看官去研究一波。

Android 使用RecycleView实现吸附小标题的Demo(附源码)



猜你喜欢

转载自blog.csdn.net/csdn_aiyang/article/details/80094302