Android-OutOfMemory,在Android 5.0上从资源中解码位图
我有一个带有Android-OutOfMemory,在Android 5.0上从资源中解码位图,android,bitmap,out-of-memory,transitions,bitmapfactory,Android,Bitmap,Out Of Memory,Transitions,Bitmapfactory,我有一个带有回收视图的活动a。RecyclerView的每个项目都由一个ImageView和一个TextView组成,如下所示: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" androi
回收视图的活动a
。RecyclerView
的每个项目都由一个ImageView
和一个TextView
组成,如下所示:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<ImageView
android:id="@+id/imageView"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:transitionName="@string/transition_image"/>
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginStart="10dp"
android:textColor="@android:color/black"
android:textSize="19sp"
android:transitionName="@string/transition_text"/>
</LinearLayout>
如您所见,当在其中一个项目中执行单击时,我启动ActivityB。以下是活动B的代码:
public class ActivityB extends AppCompatActivity{
@Override
protected void onCreate(final Bundle savedInstanceState){
supportRequestWindowFeature(Window.FEATURE_ACTIVITY_TRANSITIONS);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_b);
final Bundle args = getIntent().getExtras();
if(args != null){
final ImageView imageViewBig = (ImageView) findViewById(R.id.imageViewBig);
final int imageResource = args.getInt(ContentFragment.KEY_IMAGE);
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;
options.inScaled = true;
options.inDither = false;
final Bitmap bitmap = BitmapFactory.decodeResource(getResources(), imageResource, options);
imageViewBig.setImageBitmap(bitmap);
Palette.from(bitmap).generate(new Palette.PaletteAsyncListener(){
@Override
public void onGenerated(final Palette palette){
final Palette.Swatch profileSwatchDark = UtilPalette.getProfileSwatchDark(palette);
if(profileSwatchDark != null){
final int vibrantRGB = profileSwatchDark.getRgb();
Utils.tintSystemBars(getWindow(), vibrantRGB);
}
}
});
}
}
如您所见,播放的过渡动画将ImageView
作为共享元素:
一切正常。我的问题是,如果我点击RecyclerView
(即转到ActivityB),返回,然后再次键入一个项目,返回,等等,然后重复几次(大约10次),应用程序就会崩溃,ActivityB的位图工厂.decodeResource
方法出现OutOfMemory异常
我在Android 5.0上运行上述代码,因此我的理解是,应该自动清理以前分配的位图内存(根据Honeycom上的更改,位图的像素数据现在存储在VM内存中,而不是本机内存中,因此符合垃圾收集的条件)。但这里似乎不是这样。从ActivityA到ActivityB转换几次后,应用程序不断崩溃
此外,我可以在Android Studio上的新内存档案器屏幕上看到,每次我进入ActivityB时,内存都会不断上升(这是因为正在从资源加载大图像),但当我按下“后退”按钮时(即ActivityB完成时),内存不会下降,当达到最大值(96MB限制)时导致崩溃:
您是否尝试过显式
null
图像可绘制(例如在onDestroy()
)中)?如果这有帮助,您还可以显式回收位图,这会使任何缓存的值不可用。这通常也会给出实际问题的位置……您应该发布更多代码。看起来很有可能您正在某个地方泄漏ActivityB,因此这不是垃圾收集。@dhke我已经在onDestroy中显式地将图像drawable设置为null(如您所说),并且它似乎已经完成了这个任务!现在,当我关闭ActivityB时,内存消耗会下降。现在的问题是:为什么?为什么我们需要手动执行此操作?垃圾收集器不应该自动处理它吗?@Tiago从我收集的信息来看,位图的唯一引用由ImageView
保存,但在活动被销毁后也应该进行垃圾收集……事实上,这里也存在同样的问题。删除活动转换将使内存使用恢复正常。
public class ActivityB extends AppCompatActivity{
@Override
protected void onCreate(final Bundle savedInstanceState){
supportRequestWindowFeature(Window.FEATURE_ACTIVITY_TRANSITIONS);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_b);
final Bundle args = getIntent().getExtras();
if(args != null){
final ImageView imageViewBig = (ImageView) findViewById(R.id.imageViewBig);
final int imageResource = args.getInt(ContentFragment.KEY_IMAGE);
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;
options.inScaled = true;
options.inDither = false;
final Bitmap bitmap = BitmapFactory.decodeResource(getResources(), imageResource, options);
imageViewBig.setImageBitmap(bitmap);
Palette.from(bitmap).generate(new Palette.PaletteAsyncListener(){
@Override
public void onGenerated(final Palette palette){
final Palette.Swatch profileSwatchDark = UtilPalette.getProfileSwatchDark(palette);
if(profileSwatchDark != null){
final int vibrantRGB = profileSwatchDark.getRgb();
Utils.tintSystemBars(getWindow(), vibrantRGB);
}
}
});
}
}