【问题标题】:OutOfMemory exception when using the app for a while使用应用程序一段时间时出现 OutOfMemory 异常
【发布时间】:2015-12-14 03:36:52
【问题描述】:

我有一个复杂的应用程序,它有很多图像、位图和图标 使用该应用程序一段时间后,我在尝试扩展布局时出现内存不足异常,位图工厂抛出异常(如预期)

问题是没有页面自己崩溃,我没有使用非常大的图片,其中大多数是使用 volley 的 Web 请求

这是场景: 我有一个包含片段的活动,我切换到另一个片段,其中包含大约 15 个图像,所有这些图像都使用 Volley 实现了 BitmapLruCache(我想是正确的),这个片段工作得很好,回到前一个片段工作得很好。但是,在这两个片段之间来回突然引发OOM Exception,我没有将片段保留在内存中,我尝试使用片段事务替换和删除片段问题仍然存在

第一个片段有 3 张静态图片,其他一些是网络请求

我搜索了解决方案,但当问题在应用程序的某个点上持续存在时,一切都建议解决方案

解决这个问题的一般方法是什么?有没有办法处理/清除缓存或堆,当我更改片段时,根本不需要旧的片段

我会放一些代码,但我不知道从哪里开始!!

有什么建议吗?

编辑:我禁用了 volley requests ,我的应用现在没有网络位图

这就是我使用 BitmapLruCache 的方式

public class BitmapLruCache extends LruCache<String, Bitmap> implements ImageLoader.ImageCache {
public static int getDefaultLruCacheSize() {
    final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
    final int cacheSize = maxMemory / 8;

    return cacheSize;
}

public BitmapLruCache() {
    this(getDefaultLruCacheSize());
}

public BitmapLruCache(int sizeInKiloBytes) {
    super(sizeInKiloBytes);
}

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

@Override
public Bitmap getBitmap(String url) {
    return get(url);
}

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

编辑 2: 我在 android studio 中观察内存图,图中的每次跳转实际上是片段之间的变化,但正如我之前提到的,我该如何摆脱分段?!我之前试过删除它

编辑 3: 以下是其中一个异常的日志(正如我所提到的,它并不总是在应用程序的同一点发生)

12-10 19:44:29.396 29021-29021/com.orderme E/AndroidRuntime: FATAL EXCEPTION: main
                                                         Process: com.orderme, PID: 29021
                                                         java.lang.OutOfMemoryError: Failed to allocate a 5040012 byte allocation with 3173020 free bytes and 3MB until OOM
                                                             at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
                                                             at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
                                                             at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:726)
                                                             at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:547)
                                                             at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:1014)
                                                             at android.content.res.Resources.loadDrawableForCookie(Resources.java:3747)
                                                             at android.content.res.Resources.loadDrawable(Resources.java:3620)
                                                             at android.content.res.TypedArray.getDrawable(TypedArray.java:762)
                                                             at android.widget.ImageView.<init>(ImageView.java:151)
                                                             at android.widget.ImageView.<init>(ImageView.java:140)
                                                             at android.support.v7.widget.AppCompatImageView.<init>(AppCompatImageView.java:60)
                                                             at android.support.v7.widget.AppCompatImageView.<init>(AppCompatImageView.java:56)
                                                             at android.support.v7.internal.app.AppCompatViewInflater.createView(AppCompatViewInflater.java:98)
                                                             at android.support.v7.app.AppCompatDelegateImplV7.createView(AppCompatDelegateImplV7.java:926)
                                                             at android.support.v7.app.AppCompatDelegateImplV7.onCreateView(AppCompatDelegateImplV7.java:980)
                                                             at android.support.v4.view.LayoutInflaterCompatHC$FactoryWrapperHC.onCreateView(LayoutInflaterCompatHC.java:44)
                                                             at android.view.LayoutInflater$FactoryMerger.onCreateView(LayoutInflater.java:181)
                                                             at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:732)
                                                             at android.view.LayoutInflater.rInflate(LayoutInflater.java:813)
                                                             at android.view.LayoutInflater.inflate(LayoutInflater.java:511)
                                                             at android.view.LayoutInflater.inflate(LayoutInflater.java:415)
                                                             at android.view.LayoutInflater.inflate(LayoutInflater.java:366)
                                                             at com.orderme.Main.MainFragment.onCreateView(MainFragment.java:105)
                                                             at android.support.v4.app.Fragment.performCreateView(Fragment.java:1965)
                                                             at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1078)
                                                             at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1259)
                                                             at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:738)
                                                             at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1624)
                                                             at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:517)
                                                             at android.os.Handler.handleCallback(Handler.java:739)
                                                             at android.os.Handler.dispatchMessage(Handler.java:95)
                                                             at android.os.Looper.loop(Looper.java:145)
                                                             at android.app.ActivityThread.main(ActivityThread.java:5951)
                                                             at java.lang.reflect.Method.invoke(Native Method)
                                                             at java.lang.reflect.Method.invoke(Method.java:372)
                                                             at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1388)
                                                             at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1183)

【问题讨论】:

  • “第一个片段有 3 张静态图片” - 如果“静态”是指 static 修饰符听起来像这样可能会导致内存泄漏。你试过Android docs中的调试步骤吗?
  • 不,我不是指静态修饰符,我指的是可绘制对象中的静态,而不是来自互联网
  • 你能发布更多关于这些图片的信息(最大资产桶的维度)吗?您使用什么 xml 布局来显示它们?
  • 你也可以添加你的BitmapLruCache设置吗?
  • 请检查我的编辑

标签: android android-fragments bitmap


【解决方案1】:

假设每张图片大小为 5mb,15 张图片也没什么大不了的。验证缓存是否在 volley 中正常工作。当不再需要图像或堆越来越高时,很少有图像库不会删除缓存。说毕加索不这样做。我有类似的情况,如果你在朋友列表中上下滚动,就会出现 OOM。我正在使用毕加索库。我切换到 UIL,我再也没有看到 OOM。在毕加索中,虽然有点忙,但我不得不处理删除缓存。在 UIL 中,我不需要这样做。

因此,请查看默认情况下 volley 是否不删除缓存以及是否必须这样做。

你可以看看这个 SO post

【讨论】:

  • 每个大小都是 5mb 甚至 ...大小是多少? jpg、png 还是原生位图的数据?如果是 jpg 或 png,那么它太大而无法将其存储在内存中(因为它会暗示像 4096x4096(或类似的怪物大小)这样的大小 - 作为原生位图,它需要 ~64MB - 对于 ARGB8888)
  • 文件大小与位图内存使用无关。使用 ARGB_8888 10x10 像素的图像在解码时将占用 10x10x4 (400) 字节的内存(无论 jpg 在磁盘上是 1mb 还是 2kb)
  • 这就是我写的……但 OP 可能会认为不同。
【解决方案2】:

问题解决了! 经过 4 天的试验和堆转储和一切 原来它不在我的代码中

我将 zendesk 库降级到旧版本,它已解决!

【讨论】:

    猜你喜欢
    • 2012-05-29
    • 2011-02-17
    • 1970-01-01
    • 1970-01-01
    • 2012-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多