Gallery 的使用需要配合适配器来桥接它要展示的数据。所以比较重点的地方还是放在适配器上。下面贴出我自己写的适配器ImageAdapter的代码,代码中简单的对Gallery的使用进行了流畅性的优化,使其在水平滚动时,不会产生体验不佳的卡顿。
package com.wzp.control.Logic;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.util.SparseArray;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.ImageView;
import com.wzp.R;
import com.wzp.model.data.Scale;
public class ImageAdapter extends BaseAdapter{
// 定义Context
private Context mContext;
// 定义整型数组,即图片源
private Integer[] mImageIds = null;
private int galleryBackground;
private SparseArray<ImageView> sArray = null; // 稀疏数组,用来缓存bitmap
private int width = 0;
private int height = 0;
public ImageAdapter(Context c, Integer[] imageIds, int screenWidth, int screenHeight)
{
mContext = c;
this.mImageIds = imageIds;
sArray = new SparseArray<ImageView>(); // 创建一个稀疏数组
height = (int)(Scale.gallery_height * screenHeight);
width = (int)(Scale.gallery_width * screenWidth);
// 使用在res/values/attrs.xml中的<declare-styleable>定义
TypedArray ta = mContext.obtainStyledAttributes(R.styleable.Gallery);
// 取得Gallery属性的id
galleryBackground = ta.getResourceId(R.styleable.Gallery_android_galleryItemBackground, 0);
// 让对象的styleable属性能够反复使用
ta.recycle();
}
// 获取图片的个数
public int getCount() {
return mImageIds.length;
}
// 获取图片源
public Object getItem(int arg0) {
return arg0;
}
// 获取图片在库中的位置
public long getItemId(int arg0) {
return arg0 % mImageIds.length;
}
/**
* 取得要显示的ImageView
*/
public View getView(int arg0, View arg1, ViewGroup arg2) {
ImageView imageView = sArray.get(arg0);
if(imageView != null)
return imageView;
else
{
imageView = new ImageView(mContext);
// 按实际的大小生成的Bitmap
Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(), mImageIds[arg0]);
bm = Bitmap.createScaledBitmap(bm, width, height, false);
// 给ImageView设置资源
imageView.setImageBitmap(bm);
// 设置布局图片的宽高以指定宽高显示
imageView.setLayoutParams(new Gallery.LayoutParams(width, height));
// 设置显示比例类型
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
// 设置gallery的背景图
imageView.setBackgroundResource(galleryBackground);
sArray.put(arg0, imageView); // 把ImageView加到SparseArray稀疏数组中保存
}
return imageView;
}
/**
* 设置拼图图组的Id数组值
* @param imageIds
*/
public void setImageIds(Integer imageIds[])
{
this.mImageIds = imageIds;
recycleImageViews(); // 清理稀疏数组
}
/**
* 回收ImageView中的Bitmap所占用的内存
*/
public void recycleImageViews()
{
int size = sArray.size();
for(int i = 0; i < size; i++)
{
int key = sArray.keyAt(i); // 取得索引(范围:0至size-1)对应的key
ImageView iv = sArray.get(key);
BitmapDrawable bd = (BitmapDrawable)iv.getDrawable();
Bitmap bm = bd.getBitmap(); // 取得bitmap
bm.recycle(); // 回收bitmap的内存
bm = null;
}
sArray.clear();
}
}
在整个代码中,主要核心在getView()里面。
public View getView(int arg0, View arg1, ViewGroup arg2) {
ImageView imageView = sArray.get(arg0);
if(imageView != null)
return imageView;
else
{
imageView = new ImageView(mContext);
// 按实际的大小生成的Bitmap
Bitmap bm = BitmapFactory.decodeResource(mContext.getResources(), mImageIds[arg0]);
bm = Bitmap.createScaledBitmap(bm, width, height, false);
// 给ImageView设置资源
imageView.setImageBitmap(bm);
// 设置布局图片的宽高以指定宽高显示
imageView.setLayoutParams(new Gallery.LayoutParams(width, height));
// 设置显示比例类型
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
// 设置gallery的背景图
imageView.setBackgroundResource(galleryBackground);
sArray.put(arg0, imageView); // 把ImageView加到SparseArray稀疏数组中保存
}
return imageView;
}
Gallery中的每一张图片都是一个ImageView,如果使用ImageView imageView = new ImageView(mContext);的话,每一次调用getView就会产生一个ImageView,从而会造成浪费。所以上面使用了一个稀疏数组SparseArray(其实我当时第一次想到的并不是它,而是HashMap,但是google提示使用SparseArray来代替能够有更好的性能),SparseArray保存了创建的ImageView,而每一个ImageView都有一个对应的key,key值为ImageView在Gallery中的位置。那么这样的话,就能够产生有限的ImageView。在getView中,先判断需要显示的imageView在SparseArray中是否存在,若存在,则使用它,若不存在,则新建。这样就能够降低内存资源的浪费了,从而提高了Gallery的流畅性。同时,在给imageView设置Bitmap时,也对bitmap做了缩小,这样降低了对内存的占用。bitmap的优化可以参考我前面写的文章。