RecyclerView.Adapter的优化与封装

简介: 说实在的,敲代码和看书相比较,我还是看书或是看博文看得多,到现在好久都没练练手了,然后在简书上面看了别人对adapter的封装和优化,嘿,还真的挺不错的,adapter真的简洁了不少,看完了思路,原来这么简单的啊,他的方法可能和我不同,但是思路都是差不多的,但是我觉得我的更通俗易懂(真是不要脸啊=_=!!)。好了,开始表演真正的技术了。 项目结构图主要是对B

说实在的,敲代码和看书相比较,我还是看书或是看博文看得多,到现在好久都没练练手了,然后在简书上面看了别人对adapter的封装和优化,嘿,还真的挺不错的,adapter真的简洁了不少,看完了思路,原来这么简单的啊,他的方法可能和我不同,但是思路都是差不多的,但是我觉得我的更通俗易懂(真是不要脸啊=_=!!)。好了,开始表演真正的技术了。

项目结构图

这里写图片描述

主要是对BaseRecycleAdapter和BaseViewHolder进行封装。

好了,开始讲课了^_^。

BaseRecycleAdapter.class

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import java.util.List;
import css.lontano.coordinatorlayouttest.javabean.BaseBean;

/**
 * Created by wangqi on 2016/7/16.
 */
public abstract class BaseRecycleAdapter extends RecyclerView.Adapter<BaseViewHolder> {
    private int layoutId;
    private List<? extends BaseBean> data;
    private Context context;
    private OnItemClickListner onItemClickListner;//单击事件
    private OnItemLongClickListner onItemLongClickListner;//长按单击事件
    private boolean clickFlag = true;//单击事件和长单击事件的屏蔽标识

    /**
     *
     * @param context //上下文
     * @param layoutId  //布局id
     * @param data  //数据源
     */
    public BaseRecycleAdapter(Context context, int layoutId, List<? extends BaseBean> data) {
        this.layoutId = layoutId;
        this.data = data;
        this.context = context;
    }

    @Override
    public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(context).inflate(layoutId, parent, false);
        final BaseViewHolder holder = new BaseViewHolder(v, context);
        //单击事件回调
        v.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (clickFlag) {
                    onItemClickListner.onItemClickListner(v,holder.getLayoutPosition());
                }
                clickFlag = true;
            }
        });
        //单击长按事件回调
        v.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                onItemLongClickListner.onItemLongClickListner(v,holder.getLayoutPosition());
                clickFlag = false;
                return false;
            }
        });
        return holder;
    }

    @Override
    public void onBindViewHolder(BaseViewHolder holder, int position) {
        convert(holder, data.get(position));
    }

    protected abstract <T extends BaseBean> void convert(BaseViewHolder holder, T bean);

    @Override
    public int getItemCount() {
        return data.size();
    }

    public void setOnItemClickListner(OnItemClickListner onItemClickListner) {
        this.onItemClickListner = onItemClickListner;
    }

    public void setOnItemLongClickListner(OnItemLongClickListner onItemLongClickListner) {
        this.onItemLongClickListner = onItemLongClickListner;
    }

    public interface OnItemClickListner {
        void onItemClickListner(View v,int position);
    }

    public interface OnItemLongClickListner {
        void onItemLongClickListner(View v,int position);
    }
}

BaseRecycleAdapter类里面其实没什么,就和普通的adapter没什么区别,只是将数据的设置用抽象方法去表示,然后让继承类去实现结果操作。
看到上面的代码,大家应该看到了两个重点:
一、单击事件的回调:
RecyclerView默认是没有像ListView的onItemClick方法的,我们必须得自己去实现,我是直接给引用 的布局设置点击事件和长点击事件,这个点击事件最好是设置在onCreateViewHolder方法中,因为RecyclerAdapter初始化只调用一次,而有些人习惯设置在onBindViewHolder方法中,这样每次更新View都要去设置一遍监听事件,是没有必要的操作。大家看到我在两个事件的回调里面设置了一个clickFlag单击标记,大家知道是为了避免什么吗?操作实验过的同学应该就会知道了,假如不设置这些标志,在进行长点击操作松开手指会发现,他还会再触发一次短单击事件,所以为了避免长点击操作带来的两次回调效果,先设置clickFlag为true,此时可以短点击,当长单击操作开始时,我们设置clickFlag为false,这是长单击回调结束,进入了短单击,发现此时clickFlag是为false的,所以就不回调短单击的事件,最后又重新设置回可短单击效果,这部分要是不明白的可以给我留言。
二、数据传递用泛型
①List< ? extends BaseBean> data
② protected abstract void convert(BaseViewHolder holder, T bean);
这两个部分都是泛型的巧用,以前不会玩这些,java打的不牢,后来看鸿洋的博客,对于封装这块用的特别多,忽然发现泛型的重要性,然后重回宿舍,拿起李刚的《疯狂java讲义》狂看,看完之后,原来是这样的啊,? extends BaseBean表现为集合数据里面存储的类型是BaseBean或是BaseBean的子类,也就是向下,如果是? super BaseBean 则存储的数据类型为BaseBean或BaseBean的父类,也就是向上,大概好像是这么理解的,如有错误,大家指出来喔,
我这边存储的数据类型Model,bean都必须要继承BaseBean这个父类,因为泛型传递,所以我就这么做了,要是大家有什么好的方法的话,也可以告诉告诉我,就怕没有知识汲取。

BaseBean.class 和Person.class

这里写图片描述

BaseViewHolder.class

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

/**
 * Created by Administrator on 2016/7/16.
 */
public class BaseViewHolder extends RecyclerView.ViewHolder {
    View convertView;
    Context context;

    public BaseViewHolder(View itemView, Context context) {
        super(itemView);
        this.convertView = itemView;
        this.context = context;
    }

    public void setText(int id, String text) {
        TextView tx = (TextView) convertView.findViewById(id);
        tx.setText(text);
    }

    public void setImageResource(int id, int resouceId) {
        ImageView img= (ImageView) convertView.findViewById(id);
        img.setImageResource(resouceId);
    }

}

BaseViewHolder这个类呢一般都是拿来优化RecycleView的,然后拿到这个holder来设置数据,RecycleAdapter的onCreateViewHolder方法将填充的item布局返回给了BaseViewHolder,然后将这个view设置为全局,下面的那些setText或是setImageResource等等,大家都可以自己扩展,这些方法都是提供设置View数据的。


好了,base封装基本上完成了,接下来就是怎么用了。

RecycleAdapterTest.class

import android.content.Context;
import java.util.List;
import css.lontano.coordinatorlayouttest.BaseRecycleView.BaseRecycleAdapter;
import css.lontano.coordinatorlayouttest.BaseRecycleView.BaseViewHolder;
import css.lontano.coordinatorlayouttest.javabean.BaseBean;
import css.lontano.coordinatorlayouttest.javabean.Person;

/**
 * Created by wangqi 2016/7/16.
 */
public class RecycleAdapterTest extends BaseRecycleAdapter {


    public RecycleAdapterTest(Context context, List<Person> list) {
        super(context, R.layout.recycle_item, list);
    }


    @Override
    protected <T extends BaseBean> void convert(BaseViewHolder holder, T bean) {
        Person p = (Person) bean;
        holder.setText(R.id.text, p.getName());
    }
}

最后就是泛型的强转,然后下面调用ViewHolder的设置数据,将资源id和数据传递过去,就设置好了。

哇塞,adapter这么少的啊,真的好爽,我都佩服自己了。

主MAinActivity设置adapter就和普通设置数据一样一样的啦,基本没什么变化。

MainActivity.class

  recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        //模拟数据
        List<Person> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            Person p = new Person();
            p.setName(i+"ww");
            list.add(p);
        }

        RecycleAdapterTest adapter = new RecycleAdapterTest(this, list);
        recyclerView.setAdapter(adapter);
        adapter.setOnItemClickListner(new BaseRecycleAdapter.OnItemClickListner() {
            @Override
            public void onItemClickListner(View v, int position) {
                Toast.makeText(MainActivity.this,"单击事件回调"+position,Toast.LENGTH_SHORT).show();
            }
        });
      adapter.setOnItemLongClickListner(new BaseRecycleAdapter.OnItemLongClickListner() {
          @Override
          public void onItemLongClickListner(View v, int position) {
              Toast.makeText(MainActivity.this,"长单击事件回调"+position,Toast.LENGTH_SHORT).show();
          }
      });

item布局就是一个TextView,就没有什么了。

效果图

这里写图片描述


实力装了一次,以前看别人写这些代码,感觉好高大上啊,其实真的没有什么啊=_=,自己动手,丰衣足食。暑期以来第一篇,之前忙着看 安卓优化方面的书,等看完了,有了自己的心得,再来写一篇优化类的博文吧!!搞定!!

目录
相关文章
|
Java Android开发
Adroid RecyclerView adapter 封装
Adroid RecyclerView adapter 封装
|
Android开发
Android RecyclerView对应的适配器中方法的执行顺序和具体作用详解
Android RecyclerView对应的适配器中方法的执行顺序和具体作用详解
110 0
|
XML Java 数据处理
Android:RecyclerView封装,打造列表极简加载
此库的封装,除了刷新加载库使用了SmartRefreshLayout,其他的都是自己从0到1的开发,目前,自己已经在项目中使用,暂时没有出现任何问题,当然了,后续,也会不断的对其进行优化,增加一些其他的功能,希望有需要的小伙伴,长期关注。
342 0
构建一个可复用的自定义BaseAdapter
本节给大家带来的是构建一个可复用的自定义BaseAdapter,我们每每涉及到ListView GridView等其他的Adapter控件,都需要自己另外写一个BaseAdapter类,这样显得非常麻烦, 又比如,我们想在一个界面显示两个ListView的话,我们也是需要些两个BaseAdapter。
110 0
|
XML 缓存 算法
重学RecyclerView Adapter封装的深度思考和实现
重学RecyclerView Adapter封装的深度思考和实现
264 0
重学RecyclerView Adapter封装的深度思考和实现
|
Android开发
View事件分发相关结论的源码解析
View事件分发的三个核心方法有三个,分别是`dispatchTouchEvent`方法,`onInterceptTouchEvent`方法和`onInterceptTouchEvent`方法。 dispatchTouchEvent方法主要用来进行事件的分发。如果事件能够传递给当前View,那么此方法一定会被调用,返回结果受当前View的onTouchEvent和下级View的dispatchTouchEvent方法的影响,表示是否消耗当前事件。 onInterceptTouchEvent方法在dispatchTouchEvent方法内部调用,用来判断是否拦截某个事件,返回结果表示是否拦截
RecyclerView#smoothScrollToPosition调用RecyclerView#OnScrollListener的过程
项目中使用到了RecyclerView#smoothScrollToPosition(0)方法让Recyclerview滚动到顶部,同时给Recyclerview设置了监听器RecyclerView.OnScrollListener。
|
Java
【RecyclerView】 一、RecyclerView 最基本用法 ( 添加支持库 | 设置布局文件 | 自定义适配器 )
【RecyclerView】 一、RecyclerView 最基本用法 ( 添加支持库 | 设置布局文件 | 自定义适配器 )
744 0
【RecyclerView】 一、RecyclerView 最基本用法 ( 添加支持库 | 设置布局文件 | 自定义适配器 )
|
Android开发
listview加载性能优化之view的复用
listview加载性能优化之view的复用
|
Java Android开发
Android中Message对象复用原理
Android开发中,我们经常使用Message对象,却很少去探求其复用池的实现原理,是时候揭开它的神秘面纱了!
2677 0