由于图像缓存导致Android OOM错误?

时间:2014-02-21 01:16:07

标签: android memory

如果您认为我正在使用的应用程序如Facebook(至少会为您提供我正在做的事情的背景信息),这将会更容易理解这一点。我有一个活动使用导航器来交换片段之间的每个片段可以有一个到几个“子片段” - 将这些视为单独的帖子,其中包含文本视图,几个按钮和其中的ImageView。当创建“容器片段”时,我调用服务器并获取制作所有“子片段”所需的数据。然后我遍历数据并将所有“子片段”添加到“容器片段”的视图中。

我注意到我似乎使用了过多的内存(大约129 mb)。

当创建子片段时,我会调用此异步任务,从服务器中提取每个片段所需的图像并将它们放在ImageView中。

public class URLImageFactory extends AsyncTask<String, Void, Bitmap>
{
    ImageView imgView;
    private static final ImgCache mCache = new ImgCache();

    public URLImageFactory(ImageView bmImage) {
        this.imgView = bmImage;
    }

    @Override
    protected Bitmap doInBackground(String... urls) {
        String urldisplay = Config.SERVER_URL + urls[0].replaceAll("\\s+","%20");

        Bitmap bitmap = null;
        //If it is in the cache don't bother pulling it from the server
        if(bitmap != null)
        {
            return bitmap;
        }

        try {
            InputStream in = new java.net.URL(urldisplay).openStream();
            //This is in case we are using match_parent/wrap content
            if(imgView.getWidth() == 0 || imgView.getHeight() == 0)
            {
                bitmap = BitmapFactory.decodeStream(in);
            } else {
                bitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeStream(in),
                        imgView.getWidth(), imgView.getHeight(), false);
            }
            mCache.put(urldisplay,bitmap);
        } catch (Exception e) {
            Log.e("Error", e.getMessage());
            e.printStackTrace();
        }
        return bitmap;
    }

    @Override
    protected void onPostExecute(Bitmap result) {
        imgView.setImageBitmap(result);
    }
}

我已经初步尝试缓存图像以加快过程

公共类ImgCache扩展了LruCache {

    public ImgCache() {
        super( calculateCacheSize() );
    }

    public static int calculateCacheSize()
    {
        int maxMemory = (int) Runtime.getRuntime().maxMemory() / 8;
        int cacheSize = maxMemory;
        return cacheSize;
    }

    @Override
    protected int sizeOf( String key, Bitmap value ) {
        return value.getByteCount() / 1024;
    }
}

我的应用程序因outOfMemory异常而崩溃。我还注意到,当我的“容器片段”被替换为另一个时...通常是一个类似结构的片段......这些子片段的onPause()和onStop()没有被触发。如果它有助于子片段是静态内部类,而容器片段不是。我认为这是一个与位图相关的问题,但我不确定。当父命中onPause但我似乎没有帮助时,我试图在所有子片段上使用TransactionManager.remove(fragment)。

1 个答案:

答案 0 :(得分:2)

您将每个对象的字节数除以1024,但只将可用内存除以8;结果是LRU缓存最多可以填充128倍的可用内存量。从/ 1024移除sizeOf,您应该感觉良好。