有没有办法提高从资产加载图像的性能?

时间:2013-10-08 09:21:45

标签: android performance android-asynctask imageview

我有一个ListView,每行都有一个ImageView。

我有一个customAdapter,可以为getView函数中的每一行加载图像。

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

    View row = convertView;
    if (row == null) {
        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        row = inflater.inflate(R.layout.list_row, parent, false);
        ViewHolder viewHolder = new ViewHolder();
        viewHolder.listImage = (ImageView) row
                .findViewById(R.id.list_image);
        viewHolder.title = (TextView) row.findViewById(R.id.title);
        viewHolder.description = (TextView) row
                .findViewById(R.id.description);
        row.setTag(viewHolder);

    }


    ItemDescription des = getItemDescriptionFromFile(items.get(position)
            + "/description.txt");
    ViewHolder holder = (ViewHolder) row.getTag();
    holder.title.setText(des.title);
    holder.description.setText(des.description+(position)%5);

    holder.listImage.setImageBitmap(getBitmapFromAsset(items.get(position));
    return row;

}

private Bitmap getBitmapFromAsset(String strName) {

    InputStream istr = null;
    try {
        istr = assetManager.open(strName);
    } catch (IOException e) {
        e.printStackTrace();
    }
    Bitmap bitmap = BitmapFactory.decodeStream(istr);
    return bitmap;
}

但我注意到列表的滚动不够顺畅。

我搜索了我的问题,这个链接似乎是解决方案: http://developer.android.com/training/improving-layouts/smooth-scrolling.html

但是这段代码存在一些问题:

new AsyncTask<ViewHolder, Void, Bitmap>() {
private ViewHolder v;

@Override
protected Bitmap doInBackground(ViewHolder... params) {
    v = params[0];
    return mFakeImageLoader.getImage();
}

@Override
protected void onPostExecute(Bitmap result) {
    super.onPostExecute(result);
    if (v.position == position) {
        // If this item hasn't been recycled already, hide the
        // progress and set and show the image
        v.progress.setVisibility(View.GONE);
        v.icon.setVisibility(View.VISIBLE);
        v.icon.setImageBitmap(result);
    }
}
}.execute(holder);

我无法访问内部类AsyncTask中的位置,因为position不是final。

有没有办法进入位置?

让列表顺利滚动的最佳方法是什么?

提前致谢。

2 个答案:

答案 0 :(得分:0)

我建议您先将资产中的所有图像加载到内存中,然后再初始化适配器并从那里访问它,而不是在每次getView()调用时执行磁盘I / O.这应该会带来显着的改善。

答案 1 :(得分:0)

您可以将具有静态对象的类用作缓存。这样,类对象将资源首次加载到内存中,在下一次调用中,使用缓存的访问时间将减少。要在下面的课程中实施,您只需拨打Bitmaps.getBitmapFromAsset(context,strName)而不是自己的getBitmapFromAsset(strName)。应该注意的是,在您离开应用程序之前,以这种方式用于资产的内存将不会被释放,因为您正在使用static HastTable对象。

import java.io.IOException;
import java.io.InputStream;
import java.util.Hashtable;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;


public class Bitmaps {

    private static final Hashtable<String, Bitmap> cache = new Hashtable<String, Bitmap>();

    public static Bitmap getBitmapFromAsset(Context c, String strName) {
        synchronized (cache) {
            if (!cache.containsKey(strName)) {
                InputStream istr = null;
                try {
                    istr = c.getAssets().open(strName);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                Bitmap bitmap = BitmapFactory.decodeStream(istr);

                cache.put(strName, bitmap);
            }
            return cache.get(strName);
        }
    }

}