我的Bitmap-heavy Android应用程序有时会出现OutOfMemory错误

时间:2014-03-21 05:33:27

标签: java android bitmap

我正在创建一个非常面向图片的Android应用程序,因此我使用了很多位图。我知道使用Bitmap.recycle();帮助垃圾收集是一种好习惯,但我的应用程序的其余部分不允许我这样做。

我创建了一个名为URLImageView的类,它扩展了ImageView,允许您从URL设置图像。我在网上找到另一个名为SlidingUpPanelLayout的课程,其中ViewGroup延伸,如果我致电Bitmap.recycle();,我会收到一条错误消息,说明它无法绘制回收的位图。

任何人都可以想到一个好的解决方法,以便我释放资源,但仍然可以将它们用于SlidingUpPanelLayout吗?

以下是我创建的URLImageView课程。

public class URLImageView extends ImageView
{
private ImageLoadTask task = null;
public URLImageView(Context context)
{
    this(context, null, 0);
}

public URLImageView(Context context, AttributeSet attrs)
{
    this(context, attrs, 0);
}

public URLImageView(Context context, AttributeSet attrs, int defStyle)
{
    super(context, attrs, defStyle);
}

public void setImageFromURL(String url)
{
    //System.gc();
    Bitmap bitmap = ImageCache.getBitmapFromCache(url);
    if(bitmap == null)//the bitmap was not found in the cache, so let's actually build it
    {
        if(task != null)
            task.cancel(true);
        task = new ImageLoadTask();

        if(Build.VERSION.SDK_INT >= 11)//load the images in parallel instead of waiting
        {
            task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, url);
        } 
        else //too bad. we have to load them in series :(
        {
            task.execute(url);
        }
    }
    else//the bitmap was in the cache, so just set it
    {
        this.setImageBitmap(bitmap);
    }

    //if(bitmap != null)
    //  bitmap.recycle();
    bitmap = null;
}

private class ImageLoadTask extends AsyncTask<String, String, Bitmap>
{
    private String url;

    @Override
    protected void onPreExecute()
    {
        setImageResource(R.drawable.blank);
    }

    @Override
    protected Bitmap doInBackground(String... args)
    {
        try
        {
            //System.gc();
            url = args[0];
            Bitmap bitmap = BitmapFactory.decodeStream((InputStream)new URL(url).getContent());
            return bitmap;
        }

        catch (Exception e)
        {
            return null;
        }
    }

    @Override
    protected void onPostExecute(Bitmap bitmap)
    {
        //System.out.println("onPostExecute...");
        if(bitmap != null)
        {
            ImageCache.addBitmapToCache(url, bitmap);
            URLImageView.this.setImageBitmap(bitmap);

            //bitmap.recycle();
            bitmap = null;
        }

        else
        {
            setImageResource(R.drawable.blank);
        }
        task = null;
    }
}
}

2 个答案:

答案 0 :(得分:2)

这是因为大位图占据了RAM中的所有内容。 :d

你可以加载一个缩放的图像,这将减少很多的内存使用量,但你必须知道你的图像不会失去太多的质量。

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;
Bitmap bitmap = BitmapFactory.decodeStream(stream, null, options);

参考:http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html

答案 1 :(得分:1)

使用此函数http://developer.android.com/reference/android/graphics/Bitmap.html#createBitmap(android.graphics.Bitmap,int,int,int,int)然后你不需要回收。如果你不能缩小使用lrucache