【问题标题】:How to handle cache issues on android?如何处理android上的缓存问题?
【发布时间】:2015-12-27 00:39:19
【问题描述】:

我正在使用 Volley ImageLoader 从服务器加载图像并在我的 RecyclerView 中显示主题,这是我的 ImageLoader 的代码:

 mImageLoader=new ImageLoader(mRequestQueue,new ImageLoader.ImageCache() {

        private LruCache<String, Bitmap> cache=new LruCache<>((int)(Runtime.getRuntime().maxMemory()/1024)/8);
        @Override
        public Bitmap getBitmap(String url) {
            return cache.get(url);
        }

        @Override
        public void putBitmap(String url, Bitmap bitmap) {
            cache.put(url, bitmap);
        }
    });

我正在适配器中加载照片:

if (currentItem.myPlikPhotoUrl != null){

        imageLoader.get(
            currentItem.myPlikPhotoUrl,
            new ImageLoader.ImageListener() {
            @Override
            public void onResponse(ImageLoader.ImageContainer imageContainer, boolean b) {
                holder.myPlikPhoto.setImageBitmap(imageContainer.getBitmap());
            }

            @Override
            public void onErrorResponse(VolleyError volleyError) {

            }
        });

一切正常,但是当我滚动太快时,我得到 OOM 异常,有一些大图像,所以可能很难处理,我应该如何处理这类问题,以及正确的方法是什么处理图像加载?

Logcat 错误:

09-29 17:53:48.024    4629-4657/com.plikster.plikster I/art﹕ Clamp target GC heap from 66MB to 64MB
09-29 17:53:48.024    4629-4657/com.plikster.plikster I/art﹕ HomogeneousSpaceCompact marksweep + semispace GC freed 3(96B) AllocSpace objects, 0(0B) LOS objects, 2% free, 62MB/64MB, paused 8.700ms total 8.700ms
09-29 17:53:48.024    4629-4657/com.plikster.plikster W/art﹕ Throwing      OutOfMemoryError "Failed to allocate a 4283669 byte allocation with 1545568 free bytes and 1509KB until OOM"
09-29 17:53:48.033    4629-4658/com.plikster.plikster I/art﹕ Starting a blocking GC Alloc
09-29 17:53:48.033    4629-4658/com.plikster.plikster I/art﹕ Starting a blocking GC Alloc
09-29 17:53:48.035    4629-4657/com.plikster.plikster E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-465
Process: com.plikster.plikster, PID: 4629
java.lang.OutOfMemoryError: Failed to allocate a 4283669 byte allocation with 1545568 free bytes and 1509KB until OOM
        at java.io.ByteArrayOutputStream.toByteArray(ByteArrayOutputStream.java:122)
        at com.android.volley.toolbox.BasicNetwork.entityToBytes(BasicNetwork.java:257)
        at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:130)
        at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:114)
09-29 17:53:48.043    4629-4658/com.plikster.plikster I/art﹕ Alloc sticky concurrent mark sweep GC freed 57(9KB) AllocSpace objects, 0(0B) LOS objects, 2% free, 62MB/64MB, paused 1.877ms total 8.844ms
09-29 17:53:48.044    4629-4658/com.plikster.plikster I/art﹕ Starting a blocking GC Alloc
09-29 17:53:48.119    4629-4660/com.plikster.plikster W/EGL_emulation﹕ eglSurfaceAttrib not implemented
09-29 17:53:48.119    4629-4660/com.plikster.plikster W/OpenGLRenderer﹕ Failed to set EGL_SWAP_BEHAVIOR on surface 0x9febd780, error=EGL_SUCCESS
09-29 17:53:48.265    4629-4658/com.plikster.plikster I/art﹕ Alloc partial concurrent mark sweep GC freed 149(9KB) AllocSpace objects, 1(4MB) LOS objects, 6% free, 58MB/62MB, paused 50.522ms total 213.856ms
09-29 17:53:49.629    4629-4660/com.plikster.plikster E/Surface﹕ getSlotFromBufferLocked: unknown buffer: 0xb4017a20

在我将 ImageView 更改为 NetworkImageView 之前还有其他错误...

【问题讨论】:

  • 你在使用 NetworkImageView 吗?
  • 不,它通常的 ImageView,会有帮助吗?
  • 好吧,它是 volley 的一部分,而 NetworkImageView 就是为这种情况而设计的。 developer.android.com/training/volley/request.html
  • 谢谢,我会试试的,你的帖子为什么不这样回答?
  • 不客气,好吧,我认为这太琐碎了,无法回答,但现在我已经添加了。

标签: android image caching image-loading


【解决方案1】:

由于您已经在使用 volley,因此您可以从 ImageView 轻松切换到 NetworkImageView,并可能避免这些问题。

您可以同时使用 ImageLoader 和 NetworkImageView 来有效地 管理多个图像的显示,例如在 ListView 中。在你的 布局 XML 文件,您使用 NetworkImageView 的方式与您使用的方式大致相同 会使用 ImageView

同一页面提供了 LRU 缓存的示例代码,希望对您有用。

更新: 如果您仍然遇到 NetworkImageView 问题,您可能需要切换到基于磁盘的缓存实现。一个非常流行的磁盘缓存是 DiskLruCache 来自 ActionbarSherlock 的 Jake Warton。幸运的是,我发现了一个blog post,它解释了两者是如何集成的。

【讨论】:

  • 嗯,它没有帮助,但我有一些想法,可能是有一些太大的图像,无法保存在缓存中,或者有什么方法可以在没有缓存的情况下处理图像加载?
  • 我不知道如何,你能帮我解决这个问题吗?
  • stacktrace 与出现在 logcat 中的异常相关的错误消息一样。如果您使用的是 Eclipse,则很难从 eclipse logcat 窗口复制,但您可以在命令行上运行 logcat 并从那里获取它。 Android studio logcat 位于底部状态栏标题为 android 的选项卡中
【解决方案2】:

我建议使用Picasso 而不是这个,它会自动处理您的缓存和网络操作。

【讨论】:

  • 谢谢,但必须有一些方法,而且它很有趣,并且将来可能对处理这样的事情有用。
【解决方案3】:

减少缓存的大小。

...缓存太大会再次导致 java.lang.OutOfMemory 异常...

https://developer.android.com/training/displaying-bitmaps/cache-bitmap.html

【讨论】:

  • 最好的尺寸是多少?我该怎么计算呢?
  • @ZoltanKurtyak 答案中的链接包含设置缓存大小时要考虑的各个点。我会先将其减少 50%,以查看 OOM 错误是否消失。
猜你喜欢
  • 1970-01-01
  • 2010-09-09
  • 1970-01-01
  • 1970-01-01
  • 2015-04-06
  • 1970-01-01
  • 1970-01-01
  • 2012-06-03
  • 2014-05-31
相关资源
最近更新 更多