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,就没有什么了。

效果图

这里写图片描述


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

目录
相关文章
|
Oracle Java 关系型数据库
Oracle jdk 的国内下载镜像
Oracle jdk 的国内下载镜像
55749 0
|
iOS开发 MacOS Python
【Mac 系统】解决已有清华镜像但出现CondaHTTPError: HTTP 000 CONNECTION FAILED for url
在尝试使用清华镜像创建conda环境时遇到下载超时问题,通过删除原有镜像并添加针对Mac OS的清华镜像解决了该问题。
517 3
|
Java 开发工具
Java实现贪吃蛇大作战小游戏(完整教程+源码)额外实现积分和变速功能(上)
文章目录 1 开发环境及游戏展示 1.1 游戏主界面 1.2 移动界面 1.3 奖励界面 1.4 F加速功能界面 1.5 死亡界面 2 需求分析 3 系统设计 3.1 系统总体功能设计 3.2 系统总体流程设计 4 功能设计 4.1 贪吃蛇移动及加速功能设计 4.2 贪吃蛇吃食物加速及死亡判定功能的设计 4.2.1 贪吃蛇吃食物加速功能的设计 4.2.2 贪吃蛇死亡判定功能的设计 4.3 贪吃蛇主动加速功能的设计 4.4 贪吃蛇奖励机制功能的设计 5 项目结构与项目实现 5.1 项目结构及类间关系 5.2 项目完整源码 5.2.1 Images类
Java实现贪吃蛇大作战小游戏(完整教程+源码)额外实现积分和变速功能(上)
|
2天前
|
搜索推荐 编译器 Linux
一个可用于企业开发及通用跨平台的Makefile文件
一款适用于企业级开发的通用跨平台Makefile,支持C/C++混合编译、多目标输出(可执行文件、静态/动态库)、Release/Debug版本管理。配置简洁,仅需修改带`MF_CONFIGURE_`前缀的变量,支持脚本化配置与子Makefile管理,具备完善日志、错误提示和跨平台兼容性,附详细文档与示例,便于学习与集成。
253 116
|
17天前
|
域名解析 人工智能
【实操攻略】手把手教学,免费领取.CN域名
即日起至2025年12月31日,购买万小智AI建站或云·企业官网,每单可免费领1个.CN域名首年!跟我了解领取攻略吧~