Android ListView适配器Adapter的使用,item的复用和ViewHolder优化

概述

  • 数据适配器:由于数据源的多样性及ListView的固定数据格式,需要使用Adapter建立数据源和ListView的动态适配关系。Adapter解耦了数据的来源和显示,降低了程序的耦合性,使之更易扩展。
  • ListView的缓存机制:如需同时显示5条数据,滑动时最多会同时显示6条数据,因此系统将加载6个item布局。当向上滑动至第一个item不可见时,该item则进入缓存池。当第7条数据将被显示时,系统会自动从缓存池中取出第一个item。以此类推循环利用,节约了系统资源。


使用


1. 创建MyBean,在onCreate()中准备数据源。

public class MyBean {
    public int icon;
    public String title;
    public String content;

    public MyBean(int icon, String title, String content) {
        this.icon = icon;
        this.title = title;
        this.content = content;
    }
}

protected void onCreate(Bundle savedInstanceState) {
    ...
    // 准备数据源
    List list = new ArrayList<>();
    for (int i = 0; i < 30; i++) {
        list.add(new MyBean(
                R.mipmap.ic_launcher,
                "Title --- " + i,
                "Content --- " + i
        ));
    }
}

2. 创建MyAdapter,在onCreate()中绑定数据

public class MyAdapter extends BaseAdapter {

    private List mList;
    // 布局装载器对象
    private LayoutInflater mInflater;

    /**
     * @param context 要使用当前Adapter的界面对象
     * @param list    关联数据源和适配器
     */
    public MyAdapter(Context context, List list) {
        mInflater = LayoutInflater.from(context);
        mList = list;
    }

    // 获取ListView需要显示的数据数量
    @Override
    public int getCount() {
        return mList.size();
    }

    // 获取数据集合中指定索引对应的数据项
    @Override
    public Object getItem(int i) {
        return mList.get(i);
    }

    // 获取指定行对应item的id
    @Override
    public long getItemId(int i) {
        return i;
    }

    // 获取每个item的显示内容
    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        if (view == null) {
            view = mInflater.inflate(R.layout.item, null);
        }
        ImageView icon = (ImageView) view.findViewById(R.id.iv_item_icon);
        TextView title = (TextView) view.findViewById(R.id.tv_item_title);
        TextView content = (TextView) view.findViewById(R.id.tv_item_content);
        MyBean myBean = mList.get(i);
        icon.setImageResource(myBean.icon);
        title.setText(myBean.title);
        content.setText(myBean.content);
        return view;
    }
}

protected void onCreate(Bundle savedInstanceState) {
    ...
    // 通过Adapter绑定数据
    MyAdapter myAdapter = new MyAdapter(this, list);
    // 设置ListView显示
    listView.setAdapter(myAdapter);
}


针对反复findViewById进行优化 --- ViewHolder


通常我们会对view判空来避免重复创建大量view,优化ListView的item复用,但反复findViewById寻找控件效率仍有可提升的空间。下面将通过ViewHolder缓存显示数据的视图,进一步优化Adapter。

package com.eczom.myadapter;

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.TextView;

import java.util.List;

public class MyAdapter extends BaseAdapter {

    private List mList;
    // 布局装载器对象
    private LayoutInflater mInflater;

    /**
     * @param context 要使用当前Adapter的界面对象
     * @param list    关联数据源和适配器
     */
    public MyAdapter(Context context, List list) {
        mInflater = LayoutInflater.from(context);
        mList = list;
    }

    // 获取ListView需要显示的数据数量
    @Override
    public int getCount() {
        return mList.size();
    }

    // 获取数据集合中指定索引对应的数据项
    @Override
    public Object getItem(int i) {
        return mList.get(i);
    }

    // 获取指定行对应item的id
    @Override
    public long getItemId(int i) {
        return i;
    }

    // 获取每个item的显示内容
    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        ViewHolder viewHolder;
        // 对view判空
        if (view == null) {
            viewHolder = new ViewHolder();
            view = mInflater.inflate(R.layout.item, null);
            // 通过ViewHolder对象获取对应控件
            viewHolder.icon = (ImageView) view.findViewById(R.id.iv_item_icon);
            viewHolder.title = (TextView) view.findViewById(R.id.tv_item_title);
            viewHolder.content = (TextView) view.findViewById(R.id.tv_item_content);
            // 通过setTag()绑定ViewHolder和view
            view.setTag(viewHolder);
        } else {
            // 通过getTag()获取已绑定的ViewHolder
            viewHolder = (ViewHolder) view.getTag();
        }
        // 绑定当前数据项和item
        MyBean myBean = mList.get(i);
        viewHolder.icon.setImageResource(myBean.icon);
        viewHolder.title.setText(myBean.title);
        viewHolder.content.setText(myBean.content);
        return view;
    }

    // 创建内部类ViewHolder
    class ViewHolder {
        public ImageView icon;
        public TextView title;
        public TextView content;
    }
}

你可能感兴趣的:(Android ListView适配器Adapter的使用,item的复用和ViewHolder优化)