ListView使用总结

本文总结了ListView的使用,包括ListView的优化、BaseAdapter的封装、分割线设置、滚动条隐藏、点击反馈取消、设置空视图、头部回弹效果、聊天列表实现以及上拉加载和下拉刷新。讲解了ListView的性能优化策略,如视图复用和减少measure操作,还展示了如何实现ListView与ToolBar的交互和聊天界面的布局切换。
摘要由CSDN通过智能技术生成

ListView使用总结

虽然随着RecyclerView的不断普及,相应的资源也越来越多,许多的项目都在使用RecyclerView,但作为他的前辈ListView,加深对ListView的使用有助于我们更好的适应到RecyclerView的使用中。

首先看一下我们实现的效果一些简单效果

这里写图片描述

这只是前面的一些简单效果,后面会有一些进阶的效果,希望能耐心的看下去。

ListView的优化

ListView的优化主要包括两个方面,分别是对自身的优化以及其适配器(Adapter)的优化。

ListView自身的优化

主要包括一条。对于ListViewlayout_heightlayout_width设置为match_parent,如果设置为match_parent,一般ListView的宽高会测量三次以上。具体的源码没有深入研究。但为什么会要测量多次,如果对于自定义View稍微有点基础的会知道,对于View的测量大小有三个类型:
- UNSPECIFIED:未指定的,父类不对子类施加任何限制。
- EXACTLY:确定的,父类确定其子类控件的大小。
- AT_MOST:最大值,需要子类去测量自身大小确定。

如果我们设置宽高为wrap_content,即AT_MOST,表示其宽高有控件本身去测量确定,而如果是match_parent,则EXACTLY,表示确定的大小。

Adapter优化。

对于Adapter的优化,主要包括以下几个步骤:

  • 复用convertView,减少子布局的生成。

  • 定义ViewHolder,减少findViewById()的次数。

下面看一下代码


/**
 * 最基础的adapter
 * Created by Alex_MaHao on 2016/5/17.
 */

public class SimpleBaseAdapter extends BaseAdapter {
   

    private List<String> datas;


    public SimpleBaseAdapter(List<String> datas) {
        this.datas = datas;
    }

    @Override
    public int getCount() {
        return datas==null?0:datas.size();
    }

    @Override
    public Object getItem(int position) {
        return null;
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        ViewHolder vHolder;

        if(convertView==null){
            //初始化item布局
            convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_listview_sample,parent,false);

            //创建记事本类
            vHolder = new ViewHolder();

            //查找控件,保存控件的引用
            vHolder.tv = ((TextView) convertView.findViewById(R.id.listview_sample_tv));

            //将当前viewHolder与converView绑定
            convertView.setTag(vHolder);
        }else{
            //如果不为空,获取
            vHolder = (ViewHolder) convertView.getTag();
        }
        vHolder.tv.setText(datas.get(position));

        return convertView;
    }


    /**
     * 笔记本类,保存对象的引用
     */
    class ViewHolder{
        TextView tv;
    }
}

根据代码分析思路:
- ListView中的item滑出屏幕时,滑出的item会在getView()方法中返回,及converView参数。所以在这里判断,是否为null,如果不为null,表示我们可以对该布局重新设置数据并返回到列表中显示。
- ViewHolder,保存item中子控件的引用。因为我们复用了converView,那么对于同一个converView布局,其子控件的引用应该是不变的。所以我们可以获取到其上的所有子控件的引用并通过ViewHolder进行保存。
- setTag(),getTag():该方法实现了ViewHolderconverView的绑定,就类似于通过setTag()方法,将ViewHolder打包成一个包裹,放在了converView上,再通过getTag()方法,将这个包裹取出。

在很多优化中,会将ViewHolder定义为static。但在这里我并没加上。因为经过测试,加或不加,ViewHolder的创建次数不变。网上查了很多资料,也没有找到一个让我信服的理由。唯一有点理的就是基于java的特性。静态内部类的对象不依赖于其所在的外部类对象。

Adapter的封装–BaseAppAdapter

上一节说了Adapter的优化,但如果我们每次写都要写这么多的优化代码,这不符合程序员懒惰的天性。那我们只能把他封装,提取出一个公共的基类,在基类中,我们把布局加载,优化等都默认实现,只需让子类构造布局文件,以及绑定数据。

那么,从我们上一节的代码看,有以下模块都可以提取为基类:

  • 数据集合datas:对于数据集合,我们通常都是一个List集合,在这里定义泛型来表述其所包含的内容。
  • 数据优化:布局的复用以及ViewHolderconverView的绑定。
  • ViewHolder:定义一个ViewHolder,通过map保存控件与id;

子类所需实现的:

  • 数据的初始化
  • 确定item的布局文件
  • 将数据与视图绑定。

那么直接看一下我们继承好的代码:

public abstract  class BaseAppAdapter<T> extends BaseAdapter {
   

    /**
     * 泛型,保存数据
     */
    protected List<T> datas;

    /**
     * 构造方法,子类必须实现其构造方法,并初始化数据
     * @param datas
     */
    public BaseAppAdapter(List<T> datas) {
        this.datas = datas;
    }

    @Override
    public int getCount() {
        return datas==null?0:datas.size();
    }

    @Override
    public Object getItem(int position) {
        return null;
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        BaseViewHolder vHolder;

        if(convertView==null){
            convertView = LayoutInflater.from(parent.getContext()).inflate(getItemLayoutId(),parent,false);

            vHolder = new BaseViewHolder(convertView);

            convertView.setTag(vHolder);
        }else{
            vHolder = (BaseViewHolder) convertView.getTag();
        }

        /**
         * 数据绑定的回调
         */
        bindData(vHolder,datas.get(position));

        return convertView;
    }

    /**
     * 子类实现,获取item布局文件的id
     * @return
     */
    protected  abstract int getItemLayoutId();

    /**
     * 子类实现,绑定数据
     * @param vHolder  对应position的ViewHolder
     * @param data 对应的数据绑定
     */
    protected abstract void 
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值