android 如何避免内存不足错误
android how to avoid this out of memory error
我有很多图像说 500ish 分布在 20 个左右的片段中,图像都非常小而且加载都很好,但是我让用户可以选择 3 种不同的图像,现在如果用户更改图像时出现 OOM 错误,所以我认为这是我处理图像的方式我认为我需要先回收旧图像但我对如何做没有信心有人可以帮忙吗?
这是我如何填充我的适配器我刚刚添加了两个项目来简化事情
private void prepareCardData(){
CardWriter cardWriter = new CardWriter(getResources().getDrawable(R.drawable.dog),"DOG","dog ");
cardMakerList.add(cardWriter);
cardWriter = new CardWriter(getResources().getDrawable(R.drawable.cat_ic),"CAT","cat ");
cardMakerList.add(cardWriter);
cardAdapter.notifyDataSetChanged();
}
这就是我真正等待共享首选项更改并调用方法的地方
private SharedPreferences.OnSharedPreferenceChangeListener listener = new
SharedPreferences.OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if(key.equals("ICONS SELECTED")){
cardsChoice.setIcons(getActivity());
cardsToSet();
System.out.println("OneFrag pref listener");
}
}
};
public void cardsToSet(){
if (cardsChoice.bool_fragTwo == false) {
if (cardsChoice.group == 1) {
cardMakerList.clear();
prepareCardData();
cardsChoice.bool_fragTwo = true;
}
if (cardsChoice.group == 2) {
cardMakerList.clear();
prepareSimpleCardData();
cardsChoice.bool_fragTwo = true;
}
if (cardsChoice.group == 3) {
cardMakerList.clear();
preparePhotoCardData();
cardsChoice.bool_fragTwo = true;
}
}
}
所以如前所述,我认为我需要 运行 在它自己的线程中清理和清理不再需要的图像,但我认为还有更多其他人可以提供帮助?
这里是堆栈跟踪
06-12 17:39:47.878 13189-13219/ss.sealstudios.com.socialstories E/Surface: getSlotFromBufferLocked: unknown buffer: 0x8a12fe70
06-12 17:39:47.985 13189-13189/ss.sealstudios.com.socialstories I/System.out: OneFrag pref listener
06-12 17:39:47.987 13189-13189/ss.sealstudios.com.socialstories I/System.out: OneFrag pref listener
06-12 17:39:48.233 13189-13199/ss.sealstudios.com.socialstories I/art: Clamp target GC heap from 265MB to 256MB
06-12 17:39:48.380 13189-13189/ss.sealstudios.com.socialstories I/System.out: OneFrag pref listener
06-12 17:39:48.410 13189-13189/ss.sealstudios.com.socialstories I/art: Starting a blocking GC Alloc
06-12 17:39:48.410 13189-13189/ss.sealstudios.com.socialstories I/art: Starting a blocking GC Alloc
06-12 17:39:48.416 13189-13189/ss.sealstudios.com.socialstories I/art: Alloc sticky concurrent mark sweep GC freed 108(4KB) AllocSpace objects, 0(0B) LOS objects, 0% free, 254MB/256MB, paused 303us total 5.710ms
06-12 17:39:48.417 13189-13189/ss.sealstudios.com.socialstories I/art: Starting a blocking GC Alloc
06-12 17:39:48.433 13189-13189/ss.sealstudios.com.socialstories I/art: Clamp target GC heap from 283MB to 256MB
06-12 17:39:48.433 13189-13189/ss.sealstudios.com.socialstories I/art: Alloc partial concurrent mark sweep GC freed 5841(393KB) AllocSpace objects, 2(3MB) LOS objects, 1% free, 251MB/256MB, paused 793us total 15.361ms
06-12 17:39:48.493 13189-13189/ss.sealstudios.com.socialstories I/art: Starting a blocking GC Alloc
06-12 17:39:48.494 13189-13189/ss.sealstudios.com.socialstories I/art: Starting a blocking GC Alloc
06-12 17:39:48.502 13189-13189/ss.sealstudios.com.socialstories I/art: Alloc sticky concurrent mark sweep GC freed 17(688B) AllocSpace objects, 0(0B) LOS objects, 0% free, 255MB/256MB, paused 545us total 7.748ms
06-12 17:39:48.503 13189-13189/ss.sealstudios.com.socialstories I/art: Starting a blocking GC Alloc
06-12 17:39:48.526 13189-13189/ss.sealstudios.com.socialstories I/art: Clamp target GC heap from 287MB to 256MB
06-12 17:39:48.526 13189-13189/ss.sealstudios.com.socialstories I/art: Alloc partial concurrent mark sweep GC freed 23(944B) AllocSpace objects, 0(0B) LOS objects, 0% free, 255MB/256MB, paused 494us total 22.482ms
06-12 17:39:48.527 13189-13189/ss.sealstudios.com.socialstories I/art: Starting a blocking GC Alloc
06-12 17:39:48.567 13189-13189/ss.sealstudios.com.socialstories I/art: Clamp target GC heap from 287MB to 256MB
06-12 17:39:48.567 13189-13189/ss.sealstudios.com.socialstories I/art: Alloc concurrent mark sweep GC freed 9(12KB) AllocSpace objects, 0(0B) LOS objects, 0% free, 255MB/256MB, paused 499us total 38.887ms
06-12 17:39:48.568 13189-13189/ss.sealstudios.com.socialstories I/art: Forcing collection of SoftReferences for 2025KB allocation
06-12 17:39:48.568 13189-13189/ss.sealstudios.com.socialstories I/art: Starting a blocking GC Alloc
06-12 17:39:48.597 13189-13189/ss.sealstudios.com.socialstories I/art: Clamp target GC heap from 287MB to 256MB
06-12 17:39:48.597 13189-13189/ss.sealstudios.com.socialstories I/art: Alloc concurrent mark sweep GC freed 11(344B) AllocSpace objects, 0(0B) LOS objects, 0% free, 255MB/256MB, paused 501us total 28.481ms
06-12 17:39:48.601 13189-13189/ss.sealstudios.com.socialstories W/art: Throwing OutOfMemoryError "Failed to allocate a 2073612 byte allocation with 559872 free bytes and 546KB until OOM"
06-12 17:39:48.603 13189-13189/ss.sealstudios.com.socialstories I/art: Starting a blocking GC Alloc
06-12 17:39:48.603 13189-13189/ss.sealstudios.com.socialstories I/art: Starting a blocking GC Alloc
06-12 17:39:48.610 13189-13189/ss.sealstudios.com.socialstories I/art: Alloc sticky concurrent mark sweep GC freed 3(448B) AllocSpace objects, 0(0B) LOS objects, 0% free, 255MB/256MB, paused 484us total 6.214ms
06-12 17:39:48.611 13189-13189/ss.sealstudios.com.socialstories I/art: Starting a blocking GC Alloc
06-12 17:39:48.643 13189-13189/ss.sealstudios.com.socialstories I/art: Clamp target GC heap from 287MB to 256MB
06-12 17:39:48.643 13189-13189/ss.sealstudios.com.socialstories I/art: Alloc partial concurrent mark sweep GC freed 6(192B) AllocSpace objects, 0(0B) LOS objects, 0% free, 255MB/256MB, paused 1.131ms total 31.104ms
06-12 17:39:48.644 13189-13189/ss.sealstudios.com.socialstories I/art: Starting a blocking GC Alloc
06-12 17:39:48.673 13189-13189/ss.sealstudios.com.socialstories I/art: Clamp target GC heap from 287MB to 256MB
06-12 17:39:48.673 13189-13189/ss.sealstudios.com.socialstories I/art: Alloc concurrent mark sweep GC freed 3(96B) AllocSpace objects, 0(0B) LOS objects, 0% free, 255MB/256MB, paused 631us total 29.306ms
06-12 17:39:48.674 13189-13189/ss.sealstudios.com.socialstories I/art: Forcing collection of SoftReferences for 2025KB allocation
06-12 17:39:48.674 13189-13189/ss.sealstudios.com.socialstories I/art: Starting a blocking GC Alloc
06-12 17:39:48.704 13189-13189/ss.sealstudios.com.socialstories I/art: Clamp target GC heap from 287MB to 256MB
06-12 17:39:48.704 13189-13189/ss.sealstudios.com.socialstories I/art: Alloc concurrent mark sweep GC freed 3(96B) AllocSpace objects, 0(0B) LOS objects, 0% free, 255MB/256MB, paused 306us total 29.616ms
06-12 17:39:48.705 13189-13189/ss.sealstudios.com.socialstories W/art: Throwing OutOfMemoryError "Failed to allocate a 2073612 byte allocation with 559872 free bytes and 546KB until OOM"
06-12 17:39:48.709 13189-13189/ss.sealstudios.com.socialstories D/skia: --- allocation failed for scaled bitmap
06-12 17:39:48.709 13189-13189/ss.sealstudios.com.socialstories D/AndroidRuntime: Shutting down VM
06-12 17:39:48.724 13189-13189/ss.sealstudios.com.socialstories E/AndroidRuntime: FATAL EXCEPTION: main
Process: ss.sealstudios.com.socialstories, PID: 13189
java.lang.OutOfMemoryError: Failed to allocate a 2073612 byte allocation with 559872 free bytes and 546KB until OOM
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:609)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:444)
at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:1080)
at android.content.res.Resources.loadDrawableForCookie(Resources.java:2738)
at android.content.res.Resources.loadDrawable(Resources.java:2643)
at android.content.res.Resources.getDrawable(Resources.java:833)
at android.content.res.Resources.getDrawable(Resources.java:786)
at ss.sealstudios.com.socialstories.TwoFragment.prepareCardData(TwoFragment.java:280)
at ss.sealstudios.com.socialstories.TwoFragment.cardsToSet(TwoFragment.java:245)
at ss.sealstudios.com.socialstories.TwoFragment.onSharedPreferenceChanged(TwoFragment.java:236)
at android.app.SharedPreferencesImpl$EditorImpl.notifyListeners(SharedPreferencesImpl.java:479)
at android.app.SharedPreferencesImpl$EditorImpl.apply(SharedPreferencesImpl.java:387)
at android.preference.Preference.tryCommit(Preference.java:1419)
at android.preference.Preference.persistString(Preference.java:1452)
at android.preference.ListPreference.setValue(ListPreference.java:148)
at android.preference.ListPreference.onDialogClosed(ListPreference.java:283)
at android.preference.DialogPreference.onDismiss(DialogPreference.java:395)
at android.app.Dialog$ListenersHandler.handleMessage(Dialog.java:1328)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5527)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
如果图像视图持有位图可绘制实例
Drawable drawable = imageView.getDrawable();
if(drawable!=null && BitmapDrawable.class.isAssignableFrom(drawable.getClass())) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
Bitmap bitmap = bitmapDrawable.getBitmap();
if(bitmap != null && !bitmap.isRecycled()) bitmap.recycle();
}
但是...
如果您从不大(大到兆字节)的可绘制文件夹加载位图,那么您应该不会 运行 成为问题。
如果您加载资产,您需要检查它们是否最适合您显示它们的位置,例如,如果您显示图像的区域是尺寸为 64x64。
OOM 通常是由于加载了未知大小的图像或只是简单地将图像大小弄错而引起的,如上所述,频繁交换 ImageView 通常不会给您带来最佳图像大小的问题。
您应该阅读一些关于位图的指南:
https://developer.android.com/training/displaying-bitmaps/index.html
你的情况:
这是来自堆栈跟踪的基本片段:
FATAL EXCEPTION: main Process: ss.sealstudios.com.socialstories, PID: 13189
java.lang.OutOfMemoryError: Failed to allocate a 2073612 byte allocation with 559872 free bytes and 546KB until OOM
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:609)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:444)
at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:1080)
at android.content.res.Resources.loadDrawableForCookie(Resources.java:2738)
at android.content.res.Resources.loadDrawable(Resources.java:2643)
at android.content.res.Resources.getDrawable(Resources.java:833) at android.content.res.Resources.getDrawable(Resources.java:786)
at ss.sealstudios.com.socialstories.TwoFragment.prepareCardData(TwoFragment.java:280)
在 OOM
之前无法分配 2073612 字节的分配,其中有 559872 个可用字节和 546KB
一般来说:
- 在方法中 TwoFragment.prepareCardData(TwoFragment.java:280)
在调用 Resources.getDrawable(..) 之前,您应该获取图像视图并回收位图..
- 在fragment/activity中你还应该在 onDestroy() 方法中回收位图
如果没有更多代码,我无法确定是某个循环导致 OOM 还是您没有释放资源...
您也可以在将资源设置为图像视图之前执行此操作(缩放图像):
Out of Memory Error ImageView issue
小心!!!
不要使用你已经回收的图片。
You'll get exception: Canvas: trying to use a recycled bitmap
bitmap.recycle() 并不是 android >2.3.3 严格要求的。如果您仍然想强行回收此内存,则必须找到一种方法来检查何时确实不再需要位图(即,Canvas 有机会完成其绘制操作)。
问题是您可能大量使用位图(分配速度可能比回收位图的速度更快)然后您可能想要回收未使用的位图 ASAP.You 应该调用 recycle() 时您已完成使用位图。
Always remember don't try to recycle bitmap when it is being shown on the screen.
所以:
- 抓取对旧位图的引用
- 设置新的
- 使视图无效
- 检查旧位图是否尚未回收
- 回收旧的
- 你也可以调用System.gc(); ^
^ 指示 VM 现在是 运行 垃圾收集器的好时机。请注意,这只是一个提示。不能保证垃圾收集器实际上是 运行.
调用ImageView.setImageBitmap();或相似度不会回收位图使用的内存...
为什么?因为当您特别查看 ImageView 方法的实现时:
private void updateDrawable(Drawable d) {
if (d != mRecycleableBitmapDrawable && mRecycleableBitmapDrawable != null) {
mRecycleableBitmapDrawable.setBitmap(null);
}
...
public void setImageResource(@DrawableRes int resId) {
// The resource configuration may have changed, so we should always
// try to load the resource even if the resId hasn't changed.
final int oldWidth = mDrawableWidth;
final int oldHeight = mDrawableHeight;
updateDrawable(null);
....
public void setImageBitmap(Bitmap bm) {
// Hacky fix to force setImageDrawable to do a full setImageDrawable
// instead of doing an object reference comparison
mDrawable = null;
if (mRecycleableBitmapDrawable == null) {
mRecycleableBitmapDrawable = new ImageViewBitmapDrawable(
mContext.getResources(), bm);
} else {
mRecycleableBitmapDrawable.setBitmap(bm);
}
setImageDrawable(mRecycleableBitmapDrawable);
}
另请参阅:
https://developer.android.com/training/displaying-bitmaps/manage-memory.html
项目中的线程完成后,调用 System.gc();方法。
我有很多图像说 500ish 分布在 20 个左右的片段中,图像都非常小而且加载都很好,但是我让用户可以选择 3 种不同的图像,现在如果用户更改图像时出现 OOM 错误,所以我认为这是我处理图像的方式我认为我需要先回收旧图像但我对如何做没有信心有人可以帮忙吗?
这是我如何填充我的适配器我刚刚添加了两个项目来简化事情
private void prepareCardData(){
CardWriter cardWriter = new CardWriter(getResources().getDrawable(R.drawable.dog),"DOG","dog ");
cardMakerList.add(cardWriter);
cardWriter = new CardWriter(getResources().getDrawable(R.drawable.cat_ic),"CAT","cat ");
cardMakerList.add(cardWriter);
cardAdapter.notifyDataSetChanged();
}
这就是我真正等待共享首选项更改并调用方法的地方
private SharedPreferences.OnSharedPreferenceChangeListener listener = new
SharedPreferences.OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if(key.equals("ICONS SELECTED")){
cardsChoice.setIcons(getActivity());
cardsToSet();
System.out.println("OneFrag pref listener");
}
}
};
public void cardsToSet(){
if (cardsChoice.bool_fragTwo == false) {
if (cardsChoice.group == 1) {
cardMakerList.clear();
prepareCardData();
cardsChoice.bool_fragTwo = true;
}
if (cardsChoice.group == 2) {
cardMakerList.clear();
prepareSimpleCardData();
cardsChoice.bool_fragTwo = true;
}
if (cardsChoice.group == 3) {
cardMakerList.clear();
preparePhotoCardData();
cardsChoice.bool_fragTwo = true;
}
}
}
所以如前所述,我认为我需要 运行 在它自己的线程中清理和清理不再需要的图像,但我认为还有更多其他人可以提供帮助?
这里是堆栈跟踪
06-12 17:39:47.878 13189-13219/ss.sealstudios.com.socialstories E/Surface: getSlotFromBufferLocked: unknown buffer: 0x8a12fe70
06-12 17:39:47.985 13189-13189/ss.sealstudios.com.socialstories I/System.out: OneFrag pref listener
06-12 17:39:47.987 13189-13189/ss.sealstudios.com.socialstories I/System.out: OneFrag pref listener
06-12 17:39:48.233 13189-13199/ss.sealstudios.com.socialstories I/art: Clamp target GC heap from 265MB to 256MB
06-12 17:39:48.380 13189-13189/ss.sealstudios.com.socialstories I/System.out: OneFrag pref listener
06-12 17:39:48.410 13189-13189/ss.sealstudios.com.socialstories I/art: Starting a blocking GC Alloc
06-12 17:39:48.410 13189-13189/ss.sealstudios.com.socialstories I/art: Starting a blocking GC Alloc
06-12 17:39:48.416 13189-13189/ss.sealstudios.com.socialstories I/art: Alloc sticky concurrent mark sweep GC freed 108(4KB) AllocSpace objects, 0(0B) LOS objects, 0% free, 254MB/256MB, paused 303us total 5.710ms
06-12 17:39:48.417 13189-13189/ss.sealstudios.com.socialstories I/art: Starting a blocking GC Alloc
06-12 17:39:48.433 13189-13189/ss.sealstudios.com.socialstories I/art: Clamp target GC heap from 283MB to 256MB
06-12 17:39:48.433 13189-13189/ss.sealstudios.com.socialstories I/art: Alloc partial concurrent mark sweep GC freed 5841(393KB) AllocSpace objects, 2(3MB) LOS objects, 1% free, 251MB/256MB, paused 793us total 15.361ms
06-12 17:39:48.493 13189-13189/ss.sealstudios.com.socialstories I/art: Starting a blocking GC Alloc
06-12 17:39:48.494 13189-13189/ss.sealstudios.com.socialstories I/art: Starting a blocking GC Alloc
06-12 17:39:48.502 13189-13189/ss.sealstudios.com.socialstories I/art: Alloc sticky concurrent mark sweep GC freed 17(688B) AllocSpace objects, 0(0B) LOS objects, 0% free, 255MB/256MB, paused 545us total 7.748ms
06-12 17:39:48.503 13189-13189/ss.sealstudios.com.socialstories I/art: Starting a blocking GC Alloc
06-12 17:39:48.526 13189-13189/ss.sealstudios.com.socialstories I/art: Clamp target GC heap from 287MB to 256MB
06-12 17:39:48.526 13189-13189/ss.sealstudios.com.socialstories I/art: Alloc partial concurrent mark sweep GC freed 23(944B) AllocSpace objects, 0(0B) LOS objects, 0% free, 255MB/256MB, paused 494us total 22.482ms
06-12 17:39:48.527 13189-13189/ss.sealstudios.com.socialstories I/art: Starting a blocking GC Alloc
06-12 17:39:48.567 13189-13189/ss.sealstudios.com.socialstories I/art: Clamp target GC heap from 287MB to 256MB
06-12 17:39:48.567 13189-13189/ss.sealstudios.com.socialstories I/art: Alloc concurrent mark sweep GC freed 9(12KB) AllocSpace objects, 0(0B) LOS objects, 0% free, 255MB/256MB, paused 499us total 38.887ms
06-12 17:39:48.568 13189-13189/ss.sealstudios.com.socialstories I/art: Forcing collection of SoftReferences for 2025KB allocation
06-12 17:39:48.568 13189-13189/ss.sealstudios.com.socialstories I/art: Starting a blocking GC Alloc
06-12 17:39:48.597 13189-13189/ss.sealstudios.com.socialstories I/art: Clamp target GC heap from 287MB to 256MB
06-12 17:39:48.597 13189-13189/ss.sealstudios.com.socialstories I/art: Alloc concurrent mark sweep GC freed 11(344B) AllocSpace objects, 0(0B) LOS objects, 0% free, 255MB/256MB, paused 501us total 28.481ms
06-12 17:39:48.601 13189-13189/ss.sealstudios.com.socialstories W/art: Throwing OutOfMemoryError "Failed to allocate a 2073612 byte allocation with 559872 free bytes and 546KB until OOM"
06-12 17:39:48.603 13189-13189/ss.sealstudios.com.socialstories I/art: Starting a blocking GC Alloc
06-12 17:39:48.603 13189-13189/ss.sealstudios.com.socialstories I/art: Starting a blocking GC Alloc
06-12 17:39:48.610 13189-13189/ss.sealstudios.com.socialstories I/art: Alloc sticky concurrent mark sweep GC freed 3(448B) AllocSpace objects, 0(0B) LOS objects, 0% free, 255MB/256MB, paused 484us total 6.214ms
06-12 17:39:48.611 13189-13189/ss.sealstudios.com.socialstories I/art: Starting a blocking GC Alloc
06-12 17:39:48.643 13189-13189/ss.sealstudios.com.socialstories I/art: Clamp target GC heap from 287MB to 256MB
06-12 17:39:48.643 13189-13189/ss.sealstudios.com.socialstories I/art: Alloc partial concurrent mark sweep GC freed 6(192B) AllocSpace objects, 0(0B) LOS objects, 0% free, 255MB/256MB, paused 1.131ms total 31.104ms
06-12 17:39:48.644 13189-13189/ss.sealstudios.com.socialstories I/art: Starting a blocking GC Alloc
06-12 17:39:48.673 13189-13189/ss.sealstudios.com.socialstories I/art: Clamp target GC heap from 287MB to 256MB
06-12 17:39:48.673 13189-13189/ss.sealstudios.com.socialstories I/art: Alloc concurrent mark sweep GC freed 3(96B) AllocSpace objects, 0(0B) LOS objects, 0% free, 255MB/256MB, paused 631us total 29.306ms
06-12 17:39:48.674 13189-13189/ss.sealstudios.com.socialstories I/art: Forcing collection of SoftReferences for 2025KB allocation
06-12 17:39:48.674 13189-13189/ss.sealstudios.com.socialstories I/art: Starting a blocking GC Alloc
06-12 17:39:48.704 13189-13189/ss.sealstudios.com.socialstories I/art: Clamp target GC heap from 287MB to 256MB
06-12 17:39:48.704 13189-13189/ss.sealstudios.com.socialstories I/art: Alloc concurrent mark sweep GC freed 3(96B) AllocSpace objects, 0(0B) LOS objects, 0% free, 255MB/256MB, paused 306us total 29.616ms
06-12 17:39:48.705 13189-13189/ss.sealstudios.com.socialstories W/art: Throwing OutOfMemoryError "Failed to allocate a 2073612 byte allocation with 559872 free bytes and 546KB until OOM"
06-12 17:39:48.709 13189-13189/ss.sealstudios.com.socialstories D/skia: --- allocation failed for scaled bitmap
06-12 17:39:48.709 13189-13189/ss.sealstudios.com.socialstories D/AndroidRuntime: Shutting down VM
06-12 17:39:48.724 13189-13189/ss.sealstudios.com.socialstories E/AndroidRuntime: FATAL EXCEPTION: main
Process: ss.sealstudios.com.socialstories, PID: 13189
java.lang.OutOfMemoryError: Failed to allocate a 2073612 byte allocation with 559872 free bytes and 546KB until OOM
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:609)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:444)
at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:1080)
at android.content.res.Resources.loadDrawableForCookie(Resources.java:2738)
at android.content.res.Resources.loadDrawable(Resources.java:2643)
at android.content.res.Resources.getDrawable(Resources.java:833)
at android.content.res.Resources.getDrawable(Resources.java:786)
at ss.sealstudios.com.socialstories.TwoFragment.prepareCardData(TwoFragment.java:280)
at ss.sealstudios.com.socialstories.TwoFragment.cardsToSet(TwoFragment.java:245)
at ss.sealstudios.com.socialstories.TwoFragment.onSharedPreferenceChanged(TwoFragment.java:236)
at android.app.SharedPreferencesImpl$EditorImpl.notifyListeners(SharedPreferencesImpl.java:479)
at android.app.SharedPreferencesImpl$EditorImpl.apply(SharedPreferencesImpl.java:387)
at android.preference.Preference.tryCommit(Preference.java:1419)
at android.preference.Preference.persistString(Preference.java:1452)
at android.preference.ListPreference.setValue(ListPreference.java:148)
at android.preference.ListPreference.onDialogClosed(ListPreference.java:283)
at android.preference.DialogPreference.onDismiss(DialogPreference.java:395)
at android.app.Dialog$ListenersHandler.handleMessage(Dialog.java:1328)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5527)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
如果图像视图持有位图可绘制实例
Drawable drawable = imageView.getDrawable();
if(drawable!=null && BitmapDrawable.class.isAssignableFrom(drawable.getClass())) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
Bitmap bitmap = bitmapDrawable.getBitmap();
if(bitmap != null && !bitmap.isRecycled()) bitmap.recycle();
}
但是...
如果您从不大(大到兆字节)的可绘制文件夹加载位图,那么您应该不会 运行 成为问题。
如果您加载资产,您需要检查它们是否最适合您显示它们的位置,例如,如果您显示图像的区域是尺寸为 64x64。
OOM 通常是由于加载了未知大小的图像或只是简单地将图像大小弄错而引起的,如上所述,频繁交换 ImageView 通常不会给您带来最佳图像大小的问题。
您应该阅读一些关于位图的指南:
https://developer.android.com/training/displaying-bitmaps/index.html
你的情况:
这是来自堆栈跟踪的基本片段:
FATAL EXCEPTION: main Process: ss.sealstudios.com.socialstories, PID: 13189
java.lang.OutOfMemoryError: Failed to allocate a 2073612 byte allocation with 559872 free bytes and 546KB until OOM
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:609)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:444)
at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:1080)
at android.content.res.Resources.loadDrawableForCookie(Resources.java:2738)
at android.content.res.Resources.loadDrawable(Resources.java:2643)
at android.content.res.Resources.getDrawable(Resources.java:833) at android.content.res.Resources.getDrawable(Resources.java:786)
at ss.sealstudios.com.socialstories.TwoFragment.prepareCardData(TwoFragment.java:280)
在 OOM
之前无法分配 2073612 字节的分配,其中有 559872 个可用字节和 546KB一般来说:
- 在方法中 TwoFragment.prepareCardData(TwoFragment.java:280) 在调用 Resources.getDrawable(..) 之前,您应该获取图像视图并回收位图..
- 在fragment/activity中你还应该在 onDestroy() 方法中回收位图
如果没有更多代码,我无法确定是某个循环导致 OOM 还是您没有释放资源...
您也可以在将资源设置为图像视图之前执行此操作(缩放图像):
Out of Memory Error ImageView issue
小心!!!
不要使用你已经回收的图片。
You'll get exception: Canvas: trying to use a recycled bitmap
bitmap.recycle() 并不是 android >2.3.3 严格要求的。如果您仍然想强行回收此内存,则必须找到一种方法来检查何时确实不再需要位图(即,Canvas 有机会完成其绘制操作)。
问题是您可能大量使用位图(分配速度可能比回收位图的速度更快)然后您可能想要回收未使用的位图 ASAP.You 应该调用 recycle() 时您已完成使用位图。
Always remember don't try to recycle bitmap when it is being shown on the screen.
所以:
- 抓取对旧位图的引用
- 设置新的
- 使视图无效
- 检查旧位图是否尚未回收
- 回收旧的
- 你也可以调用System.gc(); ^
^ 指示 VM 现在是 运行 垃圾收集器的好时机。请注意,这只是一个提示。不能保证垃圾收集器实际上是 运行.
调用ImageView.setImageBitmap();或相似度不会回收位图使用的内存...
为什么?因为当您特别查看 ImageView 方法的实现时:
private void updateDrawable(Drawable d) {
if (d != mRecycleableBitmapDrawable && mRecycleableBitmapDrawable != null) {
mRecycleableBitmapDrawable.setBitmap(null);
}
...
public void setImageResource(@DrawableRes int resId) {
// The resource configuration may have changed, so we should always
// try to load the resource even if the resId hasn't changed.
final int oldWidth = mDrawableWidth;
final int oldHeight = mDrawableHeight;
updateDrawable(null);
....
public void setImageBitmap(Bitmap bm) {
// Hacky fix to force setImageDrawable to do a full setImageDrawable
// instead of doing an object reference comparison
mDrawable = null;
if (mRecycleableBitmapDrawable == null) {
mRecycleableBitmapDrawable = new ImageViewBitmapDrawable(
mContext.getResources(), bm);
} else {
mRecycleableBitmapDrawable.setBitmap(bm);
}
setImageDrawable(mRecycleableBitmapDrawable);
}
另请参阅:
https://developer.android.com/training/displaying-bitmaps/manage-memory.html
项目中的线程完成后,调用 System.gc();方法。