一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

Android开发之ListView优化方案

时间:2016-03-26 编辑:简简单单 来源:一聚教程网

我们使用ViewHolder时,把每一个item的子View控件对象都放在ViewHolder中,当第一次创建convertView对象时,便把这些item的子View控件对象findViewById实例化出来并保存到ViewHolder的对象中。然后用convertView的setTag将viewHolder对象设置到Tag中, 当以后加载ListView的item时便可以直接从Tag中取出复用ViewHolder对象中的,不需要再findViewById找item的子控件对象了。这样便大大提高了性能。

但是,某些情况下,这种优化技术便出现了一种问题,举个例子,当我们由于项目需要,需要在ListView中用到CheckBox时,那么,就会出现这样的情况:

假设一个ListView有10个Item,当我选择第一个Item的CheckBox之后,往下滑动到原先不可见的位置时就会发现,还有其他的CheckBox也被选中了,这样就造成了很不好的用户体验。

先上出现了这种问题的代码:

布局文件:

activity_listview.xml


    android:orientation="vertical" android:layout_
    android:layout_>
    android:id="@+id/listview"
    android:layout_
    android:layout_>

item_list.xml   一个CheckBox和一个TextView,设为100dp高的原因是,必须有未显示的Item,ListView才会去复用View,如果一个屏幕显示了全部的Item,那么就不回复用了。


    android:orientation="vertical" android:layout_
    android:layout_>
    android:layout_
    android:layout_>
            android:layout_centerVertical="true"
        android:layout_marginLeft="10dp"
        android:layout_
        android:layout_ />
            android:id="@+id/textView"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"
        android:layout_
        android:layout_ />


MyAdapter.java

package cn.zmit.myapplication;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import java.util.List;


/**
 * Created by Administrator on 2016/3/23.
 */
public class MyAdapter extends BaseAdapter {
    private List list;
    private Context context;

    public MyAdapter(List lists, Context contexts) {

        list = lists;
        context = contexts;
    }

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

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

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


    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            holder = new ViewHolder();
            convertView = View.inflate(context, R.layout.item_list, null);
            holder.textView = (TextView) convertView.findViewById(R.id.textView);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        holder.textView.setText(list.get(position));

        return convertView;
    }

    private class ViewHolder {
        TextView textView;
    }
}
ListVeiwDemo.java

package cn.zmit.myapplication;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2016/3/18.
 */
public class ListViewDemo extends Activity {
    private ListView listView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_listview);
        listView= (ListView) findViewById(R.id.listview);
        List list=new ArrayList<>();
        for(int i=0;i<10;i++){
            list.add(i+"");
        }
        MyAdapter adapter=new MyAdapter(list,this);
        listView.setAdapter(adapter);
    }

}
 

非常正常的一个ListView实现过程,贴代码的原因是担心有初学者不懂我在说什么。大家可以把代码拷贝一下或者自己编写看一下效果。

 

接下来说一下怎么解决!!!!
首先,定义一个Map,

Mapmap=new HashMap<>();
当convertView为null时,在convertView和子控件加载完成后,将convertView加入map:

map.put(position,convertView);
我们想一想,这时候,在前面判断的时候,还应该是

if (convertView == null)
这样吗?当然不是,换成这样:

if (map.get(position)==null)
也就是说,只要你这个Item没被加载过,就给我重新加载!

然后在下面的else里这样写:

else {
    convertView=map.get(position);
    holder = (ViewHolder) convertView.getTag();
}
假设map里有这个View,就拿出来用。

全部解决完问题的Adapter的getView部分代码为:
Mapmap=new HashMap<>();
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
    if (map.get(position)==null) {
        holder = new ViewHolder();
        convertView = View.inflate(context, R.layout.item_list, null);
        holder.textView = (TextView) convertView.findViewById(R.id.textView);
        map.put(position,convertView);
        convertView.setTag(holder);
    } else {
        convertView=map.get(position);
        holder = (ViewHolder) convertView.getTag();
    }
    holder.textView.setText(list.get(position));

    return convertView;
}

热门栏目