ListView的性能优化之convertView和viewHolder

时间:2021-12-09 22:44:05

ListView优化大致从以下几个角度:
1.复用已经生成的convertView;
2.添加viewHolder类;
3.缓存数据(图片缓存);
4.分页加载。

一、复用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,就会大大改善性能。

这连个超链接需要看看 ,写的比较好
http://www.cnblogs.com/itstudent/p/3729117.html
http://blog.csdn.net/jacman/article/details/7087995

这是我做的程序测试:
ListView的性能优化之convertView和viewHolder

看代码:

package com.example.mypic;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ListView;

public class MainActivity extends Activity {
private ListView listView;
private MyAdapter adapter;
private int[] items = new int[] { R.drawable.pc, R.drawable.pc,
R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc,
R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc,
R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc,
R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc,
R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc,
R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc,
R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc,
R.drawable.pc, R.drawable.pc, R.drawable.pc, R.drawable.pc,
R.drawable.pc, R.drawable.pc };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

listView = (ListView) findViewById(R.id.listView);
Log.v("aa", "--显示图片-1-");
adapter = new MyAdapter(this, items);
Log.v("aa", "--显示图片-2-");
listView.setAdapter(adapter);
Log.v("aa", "--显示图片-3-");
adapter.notifyDataSetChanged();
}
}
package com.example.mypic;
import android.content.Context;
import android.graphics.Bitmap;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class MyAdapter extends BaseAdapter {
private int[] items = new int[] {};
private Context context;
private String TAG = "aa";
private Bitmap bitmap = null;

public MyAdapter(Context context, int[] items) {
this.context = context;
this.items = items;
}

@Override
public int getCount() {
return items.length;
}

@Override
public Object getItem(int position) {
return items[position];
}

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

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

//Log.v(TAG, "position=="+position);
//Log.v(TAG, "convertView=="+convertView);
//Log.v(TAG, "ViewGroup=="+parent);

ViewHolder holder;
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.list_item, null);
holder = new ViewHolder();
holder.imageView = (ImageView) convertView.findViewById(R.id.imageView);
holder.textView = (TextView) convertView.findViewById(R.id.textView);

Log.v(TAG, position+"----"+holder);

convertView.setTag(holder);
}else {
holder = (ViewHolder) convertView.getTag();

Log.v(TAG, position+"--1--"+holder);
}

bitmap = BitmapCompressTools.decodeSampledBitmapFromResource(
context.getResources(), R.drawable.pc, 100, 100);

//Log.d(TAG, "压缩之后的图片大小为:" + bitmap.getByteCount());
holder.imageView.setImageBitmap(bitmap);
holder.textView.setText("图片"+position);

return convertView;
}

class ViewHolder {
ImageView imageView;
TextView textView;
}
}
package com.example.mypic;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

public class BitmapCompressTools {
public static Bitmap decodeSampledBitmapFromResource(Resources res,
int resId, int reqWidth, int reqHeight) {

// 给定的BitmapFactory设置解码的参数
final BitmapFactory.Options options = new BitmapFactory.Options();
// 从解码器中获取原始图片的宽高,这样避免了直接申请内存空间
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);

// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth,
reqHeight);

// 压缩完后便可以将inJustDecodeBounds设置为false了。
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}

/**
* 指定图片的缩放比例
*
* @param options
* @param reqWidth
* @param reqHeight
* @return
*/


public static int calculateInSampleSize(BitmapFactory.Options options,
int reqWidth, int reqHeight) {
// 原始图片的宽、高
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;

// if (height > reqHeight || width > reqWidth) {
// //这里有两种压缩方式,可供选择。
// /**
// * 压缩方式二
// */
// // final int halfHeight = height / 2;
// // final int halfWidth = width / 2;
// // while ((halfHeight / inSampleSize) > reqHeight
// // && (halfWidth / inSampleSize) > reqWidth) {
// // inSampleSize *= 2;
// // }
//
/**
* 压缩方式一
*/

// 计算压缩的比例:分为宽高比例
final int heightRatio = Math.round((float) height
/ (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
// }

return inSampleSize;
}
}

main.ml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >


<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" >

</ListView>

</RelativeLayout>

list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >


<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />


<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"/>


</LinearLayout>

这是运行结果图:
ListView的性能优化之convertView和viewHolder