Android GridView 和 ListView中若有圖片顯示的話,有時候會因為圖片size過大造成GridView 和 ListView顯示過慢。
此時可以使用非同步載入圖片的方式,先讓圖片顯示自設的default圖片,然後再開啟thread讀取實際圖片,當讀取完後立即覆蓋自設的default圖片。
程式碼如下:
pic_item.xml
main.java
此時可以使用非同步載入圖片的方式,先讓圖片顯示自設的default圖片,然後再開啟thread讀取實際圖片,當讀取完後立即覆蓋自設的default圖片。
程式碼如下:
pic_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center_horizontal"
>
<ImageView android:id="@+id/pic_list_icon"
android:layout_gravity="center_horizontal"
android:layout_width="@dimen/pic_item_icon_width"
android:layout_height="@dimen/pic_item_icon_height"
android:scaleType="fitCenter"
/>
<TextView android:id="@+id/pic_list_text"
android:layout_gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxWidth="@dimen/pic_item_icon_width"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:scrollHorizontally="true"
/>
</LinearLayout>
AsyncImageFileLoader.java
package com.test.activity.imageloader;
import java.lang.ref.SoftReference;
import java.util.HashMap;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
public class AsyncImageFileLoader {
private static String TAG = "AsyncImageFileLoader";
private HashMap<String, SoftReference<Bitmap>> imageCache;
public AsyncImageFileLoader() {
imageCache = new HashMap<String, SoftReference<Bitmap>>();
}
public Bitmap loadBitmap(final String imageFile, final int show_width, final int show_height
, final ImageCallback imageCallback)
{
//如果此圖片已讀取過的話,將會暫存在cache中,所以可以直接從cache中讀取
if (imageCache.containsKey(imageFile)) {
SoftReference<Bitmap> softReference = imageCache.get(imageFile);
Bitmap bmp = softReference.get();
if (bmp != null) {
return bmp;
}
}
final Handler handler = new Handler() {
public void handleMessage(Message message) {
imageCallback.imageCallback((Bitmap) message.obj, imageFile);
}
};
new Thread() {
@Override
public void run() {
//sleep 500ms 讓GridView可以先顯示所有item,否則會因為開始讀取圖片而使系統忙碌
//造成圖片讀取完畢後才顯示所有item
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Bitmap bmp = loadImageFromFile(imageFile, show_width, show_height);
imageCache.put(imageFile, new SoftReference<Bitmap>(bmp));
Message message = handler.obtainMessage(0, bmp);
handler.sendMessage(message);
}
}.start();
return null;
}
public Bitmap loadImageFromFile(String file, int display_width, int display_height) {
Bitmap bmp = readBitmap(file, display_width, display_height);
return bmp;
}
public interface ImageCallback {
public void imageCallback(Bitmap imageBitmap, String imageFile);
}
private static int computeSampleSize(BitmapFactory.Options opts, int minSideLength, int maxNumOfPixels)
{
int initialSize = computeInitialSampleSize(opts, minSideLength, maxNumOfPixels);
int roundedSize;
if(initialSize <= 8)
{
roundedSize = 1;
while(roundedSize < initialSize)
{
roundedSize<<=1;
}
}
else
{
roundedSize = (initialSize+7)/8*8;
}
Log.d(TAG, "roundedSize = "+roundedSize);
return roundedSize;
}
private static int computeInitialSampleSize(BitmapFactory.Options opts, int minSideLength, int maxNumOfPixels)
{
double w = opts.outWidth;
double h = opts.outHeight;
int lowerBound = (maxNumOfPixels == -1) ? 1 : (int)Math.ceil(Math.sqrt(w*h/maxNumOfPixels));
int upperBound = (maxNumOfPixels == -1) ? 128 : (int)Math.min(Math.floor(w/minSideLength),Math.floor(h/minSideLength));
if(upperBound < lowerBound)
{
return lowerBound;
}
if((maxNumOfPixels == -1) && (minSideLength == -1))
{
return 1;
}
else if(minSideLength == -1)
{
return lowerBound;
}
else
{
return upperBound;
}
}
private Bitmap readBitmap(String img_file, int show_width, int show_height)
{
Log.d(TAG, "readBitmap");
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inJustDecodeBounds = true; //設定BitmapFactory.decodeStream不decode,只抓取原始圖片的長度和寬度
BitmapFactory.decodeFile(img_file, opt);
opt.inPreferredConfig = Bitmap.Config.ARGB_8888;
opt.inPurgeable = true;
opt.inInputShareable = true;
//計算適合的縮放大小,避免OutOfMenery
opt.inSampleSize = computeSampleSize(opt, -1, show_width*show_height);
opt.inJustDecodeBounds = false;//設定BitmapFactory.decodeStream需decodeFile
Bitmap bmp = BitmapFactory.decodeFile(img_file, opt);
System.gc(); // system garbage recycle
if(bmp != null)
{
Log.d(TAG, "decodeFile success");
return bmp;
}
else
{
Log.d(TAG, "bmp == null");
return null;
}
}
}
main.java
import com.test.activity.imageloader.ImageCallback;
GridView mGridView = (GridView) findViewByOd(R.id.grid_view);
mGridView.setAdapter(new PictureListAdapter(this, mGridView, itemsArray, pathsArray))
public class PictureListAdapter extends BaseAdapter
{
GridView mGridView = null;
private LayoutInflater mInflater;
private List<String> Items;
private List<String> Paths;
private Bitmap loadingIcon;
private AsyncImageFileLoader asyncImageFileLoader;
public PictureListAdapter(Context context, GridView gridView, List<String> items, List<String> paths)
{
mInflater = LayoutInflater.from(context);
mGridView = gridView;
Items = items;
Paths = paths;
loadingIcon = BitmapFactory.decodeResource(context.getResources(), R.drawable.media_loading);
asyncImageFileLoader = new AsyncImageFileLoader();
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return Items.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return Items.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder mHolder;
if(convertView == null)
{
convertView = mInflater.inflate(R.layout.pic_item, null);
mHolder = new ViewHolder();
mHolder.icon = (ImageView) convertView.findViewById(R.id.pic_list_icon);
mHolder.text = (TextView) convertView.findViewById(R.id.pic_list_text);
convertView.setTag(mHolder);
}
else
{
mHolder = (ViewHolder) convertView.getTag();
}
mHolder.text.setText(Items.get(position).toString());
//設定此mHolder.icon的tag為檔名,讓之後的callback function可以針對此mHolder.icon替換圖片
ImageView imageView = mHolder.icon;
imageView.setTag(Paths .get(position).toString());
Bitmap cachedBitmap = asyncImageFileLoader.loadBitmap(Paths.get(position).toString(), 200, 200, new ImageCallback() {
@Override
public void imageCallback(Bitmap imageBitmap, String imageFile) {
// 利用檔案名稱找尋當前mHolder.icon
ImageView imageViewByTag = (ImageView) mGridView.findViewWithTag(imageFile);
if (imageViewByTag != null) {
if(imageBitmap != null)
imageViewByTag.setImageBitmap(imageBitmap);
}
}
});
if(cachedBitmap != null)
mHolder.icon.setImageBitmap(cachedBitmap);
else
mHolder.icon.setImageBitmap(loadingIcon); //顯示預設的圖片
return convertView;
}
private class ViewHolder
{
TextView text;
ImageView icon;
}
}
沒有留言:
張貼留言