概述

Adapter是数据和UI之间的一个桥梁,在listview,gridview等控件中都会使用到,android给我们提拱了4个adapte供我们使用:

  • BaseAdapter是一个抽象类,继承它需要实现较多的方法
  • ArrayAdapter支持泛型操作,最为简单,只能展示一行字
  • SimpleAdapter有最好的扩充性,可以自定义出各种效果
  • SimpleCursorAdapter可以适用于简单的纯文字型ListView,它需要Cursor的字段和UI的id对应起来。如需要实现更复杂的UI也可以重写其他方法。可以认为是SimpleAdapter对数据库的简单结合,可以方便地把数据库的内容以列表的形式展示出来

在实际项目中往往用的最多的还是BaseAdapter,系统提供的几个adapter大多数只有在写demo才为了图省事去用一下而已,这在包建强的《app研发录》中的也有所体现,第一章介绍adapter时就提到要求所有adpater继承自BaseAdapter,从构造函数List<自定义实体>这样的数据集合,从而完成ListView的填充工作,本篇主要总结一下BaseAdapter.

传统的方式

基本的一般只需要4步即可完成

  • 继承BaseAdapter
  • 实现getCountgetItemgetItemIdgetView
  • 书写ViewHolder内部类去存储复用View
  • getView中实现数据的设置

    下面给出一个基本的NormalAdapter实现的代码
public class NormalAdapter extends BaseAdapter {
    private LayoutInflater layoutInflater;
    private List<TestBean> datas;

    //NormalAdapter需要一个Context,通过Context获得Layout.inflater,然后通过inflater加载item的布局
    public NormalAdapter(Context context, List<TestBean> datas) {
        layoutInflater = LayoutInflater.from(context);
        this.datas = datas;
    }

    @Override
    public int getCount() {
        return datas.size();
    }

    @Override
    public Object getItem(int position) {
        return datas.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        if (convertView == null) {
            convertView = layoutInflater.inflate(R.layout.item_list, parent, false);
            holder = new ViewHolder();

            holder.tv_title = (TextView) convertView.findViewById(R.id.tv_title);
            holder.tv_des = (TextView) convertView.findViewById(R.id.tv_desc);
            holder.tv_time = (TextView) convertView.findViewById(R.id.tv_time);
            holder.tv_name = (TextView) convertView.findViewById(R.id.tv_name);

            convertView.setTag(holder);
        } else {
            //说明convertview已经被复用,已经设置过tag
            holder = (ViewHolder) convertView.getTag();
        }

        TestBean testBean = datas.get(position);
        holder.tv_title.setText(testBean.getTitle());
        holder.tv_des.setText(testBean.getDesc());
        holder.tv_time.setText(testBean.getTime());
        holder.tv_name.setText(testBean.getName());

        return convertView;
    }

    /**
     * viewHoder服务于特定的Adapter,根据对应的item_layout书写
     */
    private static class ViewHolder {
        TextView tv_title;
        TextView tv_des;
        TextView tv_time;
        TextView tv_name;

    }
}

初步封装

这样会带来一些问题,一个listview就要对应一个adpater,还要对应一个viewholder,这里有很多冗余的代码如getCountgetItemgetItemId这些可以被抽象出来,其实封装的思路很简单,主要集中在getView这个方法上,通过分析最普通的NormalAdapter可以看出,getView主要完成三个部分

  • 根据convertView是否为空来生成对应的holder
  • 根据对应的convertView来设置其控件上的数据
  • 返回convertView

    这三部分主要封装在BaseholderTool中

  • BaseAdapterTool

    BaseAdapterTool比较简单就是继承BaseAdapter重写几种方法在getView中使用BaseViewHolderTool

    关键代码如下

@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        //使用通用vierholder
        BaseViewHolderTool holder = BaseViewHolderTool.get(context, convertView, parent, layoutId, position);
        convert(holder, getItem(position));
        return holder.getBaseConvertView();
    }

    /**
     * 将该方法公布出去
     *
     * @param holder
     * @param t
     */
    public abstract void convert(BaseViewHolderTool holder, T t);
  • BaseviewHolderTool

    用来封装viewHolder,从基本的NormalAdapter可以看出,viewholder就是相当于一个缓存,根据convertView来判断是否重用holder;而convertView就是listview每个item的布局,因此需要完成解析布局的功能,这里采用更加高效的SparseArray

    代替hashmap(android推荐);holder又要肩负着获取布局控件的使命因此又要暴露出对应的方法
public class BaseViewHolderTool {
    private SparseArray<View> views;
    private int basePosition;
    private View baseConvertView;

    public BaseViewHolderTool(Context context, ViewGroup parent, int layoutId, int position) {

        this.basePosition = position;
        this.views = new SparseArray<View>();

        baseConvertView = LayoutInflater.from(context).inflate(layoutId, parent, false);
        baseConvertView.setTag(this);
    }

    /**
     * 获得convertview不同情况的holder
     *
     * @param context
     * @param convertView
     * @param parent
     * @param layoutId
     * @param position
     * @return
     */
    public static BaseViewHolderTool get(Context context, View convertView, ViewGroup parent, int layoutId, int position) {
        if (convertView == null) {
            return new BaseViewHolderTool(context, parent, layoutId, position);
        } else {
            BaseViewHolderTool holder = (BaseViewHolderTool) convertView.getTag();
            holder.basePosition = position;//更新position位置
            return holder;
        }
    }

    /**
     * 通过id获取控件
     *
     * @param viewId
     * @param <T>
     * @return
     */
    public <T extends View> T getView(int viewId) {
        View view = views.get(viewId);
        if (view == null) {
            view = baseConvertView.findViewById(viewId);
            views.put(viewId, view);
        }
        return (T) view;
    }

    public View getBaseConvertView() {
        return baseConvertView;
    }
}

效果图如下:

多个type的item

这里要谈的是多个布局同时出现在一个listview中,

这时候就需要

重写 getViewTypeCount() – 返回你有多少个不同的布局

重写 getItemViewType(int) – 由position返回view type id

然后在getview中,

int viewType = getItemViewType(position);//获取对应的类型

这里做了一个简单地demo在偶数行显示item_list2,奇数行显示item_list

  @Override
    public int getItemViewType(int position) {
        return position % 2 == 0 ? TYPE_SEPARATOR : TYPE_MAIN;
    }

效果图如下

demo已经传到github上AdapterStudy

listview中的adapter学习小结的更多相关文章

  1. android代码优化----ListView中自定义adapter的封装(ListView的模板写法)

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  2. 42.Android之ListView中ArrayAdapter简单学习

    今天学习下Android中ListView关于ArrayAdapter数据绑定, 废话少说直接上代码. 改下布局文件: <?xml version="1.0" encodin ...

  3. Java中的equals学习小结

    Java中的equals是十分重要的,和= =要区别开来,现在小结其主要内容,而且要将 = =和 equals列为重要的对比概念来学习 1.声明格式    public  boolean equals ...

  4. Mongodb中更新的学习小结

    今天继续很久没学习的mongodb的简单学习,今天来看的是更新.先来看简单的用法: use updatetest >switched to db updatetest 首先插入一下: db.th ...

  5. java中继承关系学习小结

    继承:把多个类中同样的内容提取出来.定义到一个类中,其它类仅仅须要继承该类.就能够使用该类公开的属性和公开的方法.   继承的优点:提高代码的复用性.提高代码的可维护性.让类与类之间产生关系,是多态存 ...

  6. ListView中动态显示和隐藏Header&Footer

    ListView的模板写法 ListView模板写法的完整代码: android代码优化----ListView中自定义adapter的封装(ListView的模板写法) 以后每写一个ListView ...

  7. android 自定义adapter和线程结合 + ListView中按钮滑动后状态丢失解决办法

    adapter+线程 1.很多时候自定义adapter的数据都是来源于服务器的,所以在获取服务器的时候就需要异步获取,这里就需要开线程了(线程池)去获取服务器的数据了.但这样有的时候adapter的中 ...

  8. Android学习四、Android中的Adapter

    一.Adapter的介绍 An Adapter object acts as a bridge between an AdapterView and the underlying data for t ...

  9. Android 实现ListView中Item被单击后背景色保持高亮

    今天为了解决一个需求,就是我有一个slidingDrawer,里面是一个ListView.然后,单击其中的Item,默认只是显示一个橙色背景后就恢复了.客户便有着个需求,需要单击这个Item的背景高亮 ...

随机推荐

  1. 【IOS 开发】Objective-C Foundation 框架 -- 字符串 | 日期 | 对象复制 | NSArray | NSSet | NSDictionary | 谓词

    一. 字符串 API 1. NSString 用法简介 (1) NSString API 介绍 NSString 功能 : -- 创建字符串 : 使用 init 开头的实例方法, 也可以使用 Stri ...

  2. Cocos2D瓦块地图高清屏(retina)显示比例问题的解决

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 在Cocos2D的游戏编程里,常用到瓦块地图.而cocos2D ...

  3. Mybatis3.4.0不支持mybatis-spring1.2.5及以下版本

    今天将工程的Mybatis的版本由3.3.0升级到3.4.0导致程序运行错误,使用的mybatis-spring版本是1.2.3,错误内容如下,最后发现是SpringManagedTransactio ...

  4. Oracle采购模块中的多组织访问控制(MOAC)

     1. 概述 从Release12开始启用多组织访问控制功能,将允许用户在一个单独的职责中访问一个或者多个经营单位(OU-Operation Units)的数据.这个功能允许用户在一个可共享服务的 ...

  5. JAVA之旅(二十六)——装饰设计模式,继承和装饰的区别,LineNumberReader,自定义LineNumberReader,字节流读取操作,I/O复制图片

    JAVA之旅(二十六)--装饰设计模式,继承和装饰的区别,LineNumberReader,自定义LineNumberReader,字节流读取操作,I/O复制图片 一.装饰设计模式 其实我们自定义re ...

  6. 用SpriteBuilder简化"耕牛遍地走"的动画效果(四)

    写到这突然有童鞋质疑,你这哪里是牛,分明是熊嘛! 仔细看了下,还真像牛.反正是这个意思.怪本猫猪牛熊不分,好在道理是一样的. 下面继续,言归正传. 添加一个空白的touchBegan方法,如果没有这个 ...

  7. 中国电信中兴F460光猫破解及路由级联设置

    http://blog.csdn.net/pipisorry/article/details/50636541 中国电信中兴F460光猫破解,获取超级密码,修改配置. 之前家里的宽带升级了,换成了光纤 ...

  8. Mat, IplImage, CvMat, Cvarr关系及元素获取

    自己目前正打算整理opencv数据结构之间关系,寻寻觅觅之间,发现这篇博文很全面,总结得很好,故转之.红色部分不对,自己已修改! 原文地址:http://blog.csdn.net/abcjennif ...

  9. 利用gradle添加构建版本号

    在java的程序中,貌似都没有这个构建版本号的概念,用的诸如eclipse, idea和android studio的IDE也没有直接提供构建版本号的选项.不过我却想在android程序的版本号当中添 ...

  10. matlab中 mcc/mbuild/mex 区别

    mcc 的作用是将 .m文件编译为 c/c++动态链接库文件,使你可以在 c/c++程序中使用 matlab的一些函数功能.mcc 也可以将.m文件编译为exe可执行文件. mex 的作用是将 c/c ...