ListView优化

    ListView的优化和适配器的View getView(int position, View convertView, ViewGroup parent)方法有关。重点在于getView方法返回的View是怎样产生的,以及该View的数据是怎样设置的。针对这两方面,接下来说说getView方法中的convertView参数是什么,以及ViewHolder模式。

    1.convertView参数。

    convertView是啥?官方的说法是“The old view to reuse”,即“可再利用的旧的View对象”。在详细讨论convertView之前,需要先说一下ListView中的recycle机制。

   

    上图是一个ListView的例子。我们知道ListView中每个列表项都是一个View对象,并是由getView方法返回的。说到这可能有人会想,如果我的ListView下拉后共有1000或10000个列表项,那系统是不是在内存中建立了1000或10000个View对象呢?我要说,答案是definitely not.这样的内存占用对Android设备来说简直是噩梦。于是recycle机制诞生了。如下图。

    ①.列表下拉,至Item1刚好被拉出ListView的边界,item9刚好还没进入视野。

    ②.假设Item 1的类型为Type 01。Item 1对应的View对象赋值给Type 01的convertView。这里列表项的类型是由int getItemViewType(int position)返回的。

    ③.当下拉后,在Item9刚要进入视野的那个瞬间之前,系统要调用View getView(int position, View convertView, ViewGroup parent)来返回Item9对应的View对象,而传入的convertView就是“已经用完了的Item1的View对象”,这样就达到了重新利用已用完的item的内存的效果,不用重新分配内存。然后我们就可以对convertView的数据进行修改后(因为未修改的convertView还是上一个用完的Item的数据,这里是Item1),在getView方法中return convertView。

    刚刚接触ListView的筒子们在override getView方法时会这么去写

public View getView(int position, View convertView, ViewGroup parent) {
    LayoutInflater inflater=LayoutInflater.from(context);
    View view=inflater.inflate(R.layout.files_list_item, parent, false);
    return view;
}
    也就是说根本不去利用convertView,每次产生一个新列表项时都自行创建一个View对象。这样做性能上是有缺憾的,因为对于操作系统来说,分配内存和清理内存是很耗时的操作。利用了convertView,可以大幅减少分配内存的操作(如上图中只需分配出8个View对象的内存,即能够显示的Item的数量的最大值)。

    值得一提的是,在override getView方法时,要去判断convertView参数是否为null。因为在列表刚刚建立时,是没有Item被完全从视野中拉出的,所以convertView也就没被赋值,即为null。

    2.ViewHolder模式

    ViewHolder模式的存在是为了减少convertView.findViewById(int id)的次数,从而优化性能。具体代码

static class ViewHolder{
    public TextView TextView;
}

public View getView(int position, View convertView, ViewGroup parent) {
    View view;
    if(convertView==null){
        LayoutInflater inflater = LayoutInflater.from(context);
        view=inflater.inflate(R.layout.list_item,parent,false);
        ViewHolder viewHolder=new ViewHolder();
        viewHolder.textView=view.findViewById(R.id.text);
        view.setTag(viewHolder);
}else{
    view=convertView;
}
    ViewHolder viewHolder=(ViewHolder)view.getTag();
    viewHolder.textView.setText("这里设置文本");
    return view;
}
    View.setTag(Object object)方法可以允许View对象携带数据。ViewHolder模式的思想就是把convertView中需要更改数据的视图找出来,然后用setTag方法记下,这样,之后就不用再调用findViewById(int id)来寻找视图了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值