Android - ViewHolder优化ListView

效果

本文的合集已经编著成书,高级Android开发强化实战,欢迎各位读友的建议和指导。
在京东即可购买:https://item.jd.com/12385680.html

Book

在Android开发中, ListView是重要的组件, 它以列表形式根据数据的长度, 自适应展示具体内容. 用户可以自由的定义ListView每一列的布局.
当listview有大量数据需要加载的时候, 会占据内存, 影响性能. 这时候就需要按需填充, 并重新使用View, 减少对象的创建.
ListView加载数据都是在getView()方法中进行. 同时, 需要自定义ListView重写ListAdapter: 如BaseAdapter, SimpleAdapter, CursorAdapter等.
优化ListView加载速度, 要让convertView匹配列表类型, 并最大程度的重用convertView.

getView()的加载方法一般有以下三种方式:
(1) 最慢的加载方式: 每次都重新定义一个View, 并载入布局再加载数据.

    public View getView(int position, View convertView, ViewGroup parent) {
        View item = mInflater.inflate(R.layout.list_item_icon_text, null);
        ((TextView) item.findViewById(R.id.text)).setText(DATA[position]);
        ((ImageView) item.findViewById(R.id.icon)).setImageBitmap(
                (position & 1) == 1 ? mIcon1 : mIcon2);
        return item;
    }

(2) 较快的加载方式: 当convertView不为空时, 直接重用convertView, 从而减少不必要的View创建,然后加载数据.

    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.item, parent, false);
        }
        ((TextView) convertView.findViewById(R.id.text)).setText(DATA[position]);
        ((ImageView) convertView.findViewById(R.id.icon)).setImageBitmap(
                (position & 1) == 1 ? mIcon1 : mIcon2);
        return convertView;
    }

(3) 最快的较方式: 定义一个ViewHolder,将convetView的tag设置为ViewHolder, 不为空时重用ViewHolder即可.

    static class ViewHolder {
        TextView text;
        ImageView icon;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;

        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.list_item_icon_text,
                    parent, false);
            holder = new ViewHolder();
            holder.text = (TextView) convertView.findViewById(R.id.text);
            holder.icon = (ImageView) convertView.findViewById(R.id.icon);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        holder.text.setText(DATA[position]);
        holder.icon.setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2);
        return convertView;
    }

三种方式的效率对比:

效果

当处理一些耗时的资源加载时, 做到以下几点, 可使你的加载更快更平滑:
(1) 适配器在界面主线程中进行修改
(2) 可以在任何地方获取数据但应该在另外一个地方请求数据
(3) 在主界面的线程中提交适配器的变化并调用notifyDataSetChanged()方法(更新数据源)

标准写法

package me.chunyu.Pedometer.adapter;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;


/**
 * 数据列表的适配器
 * <p/>
 * Created by wang on 15/8/10.
 */
public class DataListAdapter extends ArrayAdapter<DataListAdapter.DataItem> {

    private static class ViewHolder {
        ImageView icon;
        TextView desc;
        TextView data;
    }

    public DataListAdapter(Context context, ArrayList<DataItem> items) {
        super(context, R.layout.item_center_data, items);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        DataItem item = getItem(position);
        ViewHolder holder;

        if (convertView == null) {
            convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_center_data, parent, false);
            holder = new ViewHolder();
            holder.icon = (ImageView) convertView.findViewById(R.id.center_iv_item_sort);
            holder.desc = (TextView) convertView.findViewById(R.id.center_tv_item_desc);
            holder.data = (TextView) convertView.findViewById(R.id.center_tv_item_data);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        holder.icon.setImageResource(item.getResource());
        holder.desc.setText(item.getDesc());
        holder.data.setText(item.getData());

        return convertView;
    }


    // 数据项
    public static class DataItem {
        private int mResource;
        private String mDesc;
        private String mData;

        public DataItem(int resource, String desc, String data) {
            mResource = resource;
            mDesc = desc;
            mData = data;
        }

        public int getResource() {
            return mResource;
        }

        public String getDesc() {
            return mDesc;
        }

        public String getData() {
            return mData;
        }
    }
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CarolineSpike

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值