天天看點

Android - ViewHolder優化ListView

Android - ViewHolder優化ListView

本文的合集已經編著成書,進階Android開發強化實戰,歡迎各位讀友的建議和指導。

在京東即可購買:https://item.jd.com/12385680.html

Android - ViewHolder優化ListView

在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 & ) ==  ? 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 & ) ==  ? 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 & ) ==  ? mIcon1 : mIcon2);
        return convertView;
    }
           

三種方式的效率對比:

Android - ViewHolder優化ListView

當處理一些耗時的資源加載時, 做到以下幾點, 可使你的加載更快更平滑:

(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;
        }
    }
}