ListView使用总结

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
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
ListView是C++Builder中常用的一种控件,用于以列表的形式展示数据。下面是ListView控件的用法和示例总结。 1. 加入控件 在C++Builder中,我们可以通过拖拽的方式将ListView控件添加到窗体中。也可以在代码中使用下面的代码创建控件并添加到窗体中。 ```cpp TListView *lv = new TListView(Form1); lv->Parent = Form1; lv->Align = alClient; ``` 2. 设置样式 ListView控件提供了多种样式,可以通过Style属性来设置。我们可以设置为vsReport模式来展示表格,也可以设置为vsIcon模式来展示图标等。 ```cpp lv->ViewStyle = vsReport; ``` 3. 添加列 在ListView中,我们需要添加列来表示数据的不同字段。可以通过Columns属性来访问列,并使用Add方法来添加列。 ```cpp lv->Columns->Add()->Caption = "Name"; lv->Columns->Add()->Caption = "Age"; ``` 4. 添加行 在ListView中,我们需要添加行来表示数据的不同记录。可以通过Items属性来访问行,并使用Add方法来添加行。 ```cpp TListItem* item = lv->Items->Add(); item->Caption = "Tom"; item->SubItems->Add("18"); ``` 5. 设置单元格数据 在ListView中,我们可以通过访问行和列的交叉位置来设置单元格数据。例如,我们可以通过下面的代码设置第2行第1列的数据为"Jerry"。 ```cpp lv->Items->Item[1]->SubItems->Strings[0] = "Jerry"; ``` 6. 选择行 在ListView中,我们可以通过Selected属性来访问选中的行。例如,我们可以通过下面的代码获取选中行的数量。 ```cpp int count = lv->Selected->Count; ``` 7. 删除行 在ListView中,我们可以通过Items属性访问行,并使用Delete方法来删除行。例如,我们可以通过下面的代码删除第2行。 ```cpp lv->Items->Delete(1); ``` 8. 排序 在ListView中,我们可以通过SortType属性来设置排序方式。例如,我们可以通过下面的代码将ListView按照第2列升序排序。 ```cpp lv->SortType = stData; lv->Column[1]->Tag = 0; lv->CustomSort(NULL, 1); ``` 以上就是ListView控件的用法和示例总结。希望对你有帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值