Android ListView使用

一、ListView的使用

1、适配器代码

import java.util.List;
import cn.com.ista.pdachina.R;
import cn.com.ista.pdachina.bean.Task;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
/*
 * 任务列表数据适配器
 * @author guopeng
 * @created 2015年11月19日
 */
public class TaskListAdapter extends BaseAdapter {

    private Context context;//运行上下文
    private LayoutInflater listContainer;//视图容器,用来导入布局
    private List<自定义类> listitems;//数据集合
    
    static class ViewHolder   
    {  
        private LinearLayout layout;
        private ImageView imageView;
        private TextView taskNumber;
        private TextView taskLocation;
        private TextView taskPostCode;
        private TextView taskCity;
    }
    /*
     * 实例化Adapter
     */
    public TaskListAdapter(Context context, List<Task> listItems)
    {
        this.context = context;
        this.listContainer = LayoutInflater.from(context); //创建视图容器并设置上下文
        this.listitems = listItems;
    }
    
    @Override
    public int getCount() {
        return listitems.size();
    }

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

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        
        Task task = listitems.get(position);
        ViewHolder holder = null;
        
        if(convertView == null)
        {
            holder = new ViewHolder();
            //获取tasklist布局文件的视图
            convertView = listContainer.inflate(R.layout.tasklist_listitem, null);

            //获取控件对象
            holder.layout = (LinearLayout) convertView.findViewById(R.id.tasklist_listitem_layout);
            holder.taskNumber = (TextView) convertView.findViewById(R.id.tasklist_listitem_tasknum);
            holder.imageView= (ImageView) convertView.findViewById(R.id.tasklist_listitem_image);
            holder.taskLocation = (TextView) convertView.findViewById(R.id.tasklist_listitem_tasklocation);
            holder.taskPostCode =     (TextView) convertView.findViewById(R.id.tasklist_listitem_taskpostcode);
            holder.taskCity = (TextView) convertView.findViewById(R.id.tasklist_listitem_taskcity);
            
            convertView.setTag(holder);
        }        
        else 
        {
           holder = (ViewHolder) convertView.getTag();
        }
        
        //设置图片和文字
        switch (task.getExecutionState()) 
        {
        case 0:
            holder.layout.setBackgroundResource(R.drawable.tasklist_listitem_undisposed_bg);
            holder.imageView.setBackgroundResource(R.drawable.tasklist_listitem_undisposed_mark);
            break;
        case 1:
            holder.layout.setBackgroundResource(R.drawable.tasklist_listitem_beingprocessed_bg);
            holder.imageView.setBackgroundResource(R.drawable.tasklist_listitem_beingprocessed_mark);
            break;
        case 2:
            holder.layout.setBackgroundResource(R.drawable.tasklist_listitem_completed_bg);
            holder.imageView.setBackgroundResource(R.drawable.tasklist_listitem_completed_mark);
            break;
        case 3:
            holder.layout.setBackgroundResource(R.drawable.tasklist_listitem_canceled_bg);
            holder.imageView.setBackgroundResource(R.drawable.tasklist_listitem_canceled_mark);
            break;
        }
        
        holder.taskNumber.setText(String.valueOf(task.getId()));
        holder.taskLocation.setText(task.getPropertyName()+task.getBuildingName());
        holder.taskPostCode.setText(task.getZipCode());
        holder.taskCity.setText(task.getCity());
        
        return convertView;
    }

}

ViewHolder重用时候一定要注意先获取ViewHolder对象,然后赋值,不然就可能出现滑动时数据显示错乱问题。

2、调用

private void initData()
    {
        List<自定义类> data;final TaskListAdapter adapter = new  TaskListAdapter(appContext, data);
        listView.setAdapter(adapter);
        
        listView.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
                    long arg3) {
            }
        });
    }

二、Listview性能优化(ViewHolder重用机制)

  ListView优化主要有下面几个方面:

  1、convertView重用

  2、ViewHolder的子View复用

  3、缓存数据复用

1、convertView重用

首先讲下ListView的原理:ListView中的每一个Item显示都需要Adapter调用一次getView()的方法,这个方法会传入一个convertView的参数,这个方法返回的View就是这个Item显示的View。如果当Item的数量足够大,再为每一个Item都创建一个View对象,必将占用很多内存空间,即创建View对象(mInflater.inflate(R.layout.lv_item, null);从xml中生成View,这是属于IO操作)是耗时操作,所以必将影响性能。Android提供了一个叫做Recycler(反复循环)的构件,就是当ListView的Item从滚出屏幕视角之外,对应Item的View会被缓存到Recycler中,相应的会从生成一个Item,而此时调用的getView中的convertView参数就是滚出屏幕的缓存Item的View,所以说如果能重用这个convertView,就会大大改善性能。

那么,我们怎么重用它呢?贴代码:

@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        
        Task task = listitems.get(position);
        ViewHolder holder = null;
        
        if(convertView == null)
        {
            holder = new ViewHolder();
            //获取tasklist布局文件的视图
            convertView = listContainer.inflate(R.layout.tasklist_listitem, null);

//获取控件对象
            holder.layout = (LinearLayout) convertView.findViewById(R.id.tasklist_listitem_layout);
            holder.taskNumber = (TextView) convertView.findViewById(R.id.tasklist_listitem_tasknum);
            holder.imageView= (ImageView) convertView.findViewById(R.id.tasklist_listitem_image);
            holder.taskLocation = (TextView) convertView.findViewById(R.id.tasklist_listitem_tasklocation);
            holder.taskPostCode =     (TextView) convertView.findViewById(R.id.tasklist_listitem_taskpostcode);
            holder.taskCity = (TextView) convertView.findViewById(R.id.tasklist_listitem_taskcity);
            
            convertView.setTag(holder);
        }        
        else 
        {
           holder = (ViewHolder) convertView.getTag();
        }

当这个convertView不存在时,即第一次使用它,我们就创建一个item布局的View对象并赋给convertView,以后使用convertView时,只需从convertView中getTag取出来就可以,不需要再次创建item的布局对象了,这样便提高了性能。

2、使用ViewHolder重用

我们都知道在getView()方法中的操作是这样的:先从xml中创建view对象(inflate操作,我们采用了重用convertView方法优化),然后在这个view去findViewById,找到每一个item的子View的控件对象,如:ImageView、TextView等。这里的findViewById操作是一个树查找过程,也是一个耗时的操作,所以这里也需要优化,就是使用ViewHolder,把每一个item的子View控件对象都放在Holder中,当第一次创建convertView对象时,便把这些item的子View控件对象findViewById实例化出来并保存到ViewHolder对象中。然后用convertView的setTag将viewHolder对象设置到Tag中, 当以后加载ListView的item时便可以直接从Tag中取出复用ViewHolder对象中的,不需要再findViewById找item的子控件对象了。这样便大大提高了性能。

贴个完整的代码:

@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        
        Task task = listitems.get(position);
        ViewHolder holder = null;
        
        if(convertView == null)
        {
            holder = new ViewHolder();
            //获取tasklist布局文件的视图
            convertView = listContainer.inflate(R.layout.tasklist_listitem, null);

            //获取控件对象
            holder.layout = (LinearLayout) convertView.findViewById(R.id.tasklist_listitem_layout);
            holder.taskNumber = (TextView) convertView.findViewById(R.id.tasklist_listitem_tasknum);
            holder.imageView= (ImageView) convertView.findViewById(R.id.tasklist_listitem_image);
            holder.taskLocation = (TextView) convertView.findViewById(R.id.tasklist_listitem_tasklocation);
            holder.taskPostCode =     (TextView) convertView.findViewById(R.id.tasklist_listitem_taskpostcode);
            holder.taskCity = (TextView) convertView.findViewById(R.id.tasklist_listitem_taskcity);
            
            convertView.setTag(holder);
        }        
        else 
        {
           holder = (ViewHolder) convertView.getTag();
        }
        
        //设置图片和文字
        switch (task.getExecutionState()) 
        {
        case 0:
            holder.layout.setBackgroundResource(R.drawable.tasklist_listitem_undisposed_bg);
            holder.imageView.setBackgroundResource(R.drawable.tasklist_listitem_undisposed_mark);
            break;
        case 1:
            holder.layout.setBackgroundResource(R.drawable.tasklist_listitem_beingprocessed_bg);
            holder.imageView.setBackgroundResource(R.drawable.tasklist_listitem_beingprocessed_mark);
            break;
        case 2:
            holder.layout.setBackgroundResource(R.drawable.tasklist_listitem_completed_bg);
            holder.imageView.setBackgroundResource(R.drawable.tasklist_listitem_completed_mark);
            break;
        case 3:
            holder.layout.setBackgroundResource(R.drawable.tasklist_listitem_canceled_bg);
            holder.imageView.setBackgroundResource(R.drawable.tasklist_listitem_canceled_mark);
            break;
        }
        
        holder.taskNumber.setText(String.valueOf(task.getId()));
        holder.taskLocation.setText(task.getPropertyName()+task.getBuildingName());
        holder.taskPostCode.setText(task.getZipCode());
        holder.taskCity.setText(task.getCity());
        
        return convertView;
    }
static class ViewHolder   
    {  
        private LinearLayout layout;
        private ImageView imageView;
        private TextView taskNumber;
        private TextView taskLocation;
        private TextView taskPostCode;
        private TextView taskCity;
    }
原文地址:https://www.cnblogs.com/guop/p/4981404.html