加载活动时出现内存溢出错误

3

我有一个非常简单的活动,如下所示:

public class SurvivalActivity extends Activity {
    private static final String KEY_LAYOUT_ID = "SurvivalLayoutId";
    int mLayoutId;
    private static final int[] mSurvivalLayouts = {
        R.layout.survival1,
        R.layout.survival2,
        R.layout.survival3,
    };

    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        final Intent i = getIntent();
        if (savedInstanceState != null && savedInstanceState.containsKey(KEY_LAYOUT_ID)) {
            mLayoutId = savedInstanceState.getInt(KEY_LAYOUT_ID, 0);
        } else if (i != null) {
            mLayoutId = i.getIntExtra(KEY_LAYOUT_ID, 0);
        } else {
            mLayoutId = 0;
        }

        // Layout
        setContentView(mSurvivalLayouts[mLayoutId]);

        // Title
        Util.setTitleFont(this, findViewById(R.id.title));

        // "Next" button
        final View nextButton = findViewById(R.id.survival_next);
        Util.setFont(this, nextButton, "Lobster.ttf");
        nextButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(final View v) {
                final Intent next = new Intent(SurvivalActivity.this, SurvivalActivity.class);
                next.putExtra(KEY_LAYOUT_ID, (mLayoutId + 1) % mSurvivalLayouts.length);
                startActivity(next);
                finish();
            }
        });
    }

    @Override
    protected void onSaveInstanceState(final Bundle outState) {
        outState.putInt(KEY_LAYOUT_ID, mLayoutId);
    }
}

这两个Util.*静态方法只是改变TextView的字体。
这3个布局都相当简单,让我向您展示第一个:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <TextView
            style="@style/Title"
            android:text="@string/surv1_title" />

        <TextView
            style="@style/Content"
            android:text="@string/surv1_1" />

        <ImageView
            style="@style/Picture"
            android:src="@drawable/surv_crafting" />
        <TextView
            style="@style/PicLegend"
            android:src="@string/surv_crafting_leg" />
        <ImageView
            style="@style/Picture"
            android:src="@drawable/surv_hache" />
        <TextView
            style="@style/PicLegend"
            android:src="@string/surv_hache_leg" />
        <ImageView
            style="@style/Picture"
            android:src="@drawable/surv_pioche" />
        <TextView
            style="@style/PicLegend"
            android:src="@string/surv_pioche_leg" />

        <TextView
            style="@style/Content"
            android:text="@string/surv1_2" />

        <ImageView
            style="@style/Picture"
            android:src="@drawable/surv_charbon" />
        <TextView
            style="@style/PicLegend"
            android:src="@string/surv_charbon_leg" />

        <TextView
            style="@style/Content"
            android:text="@string/surv1_3" />

        <ImageView
            style="@style/Picture"
            android:src="@drawable/surv_torch" />
        <TextView
            style="@style/PicLegend"
            android:src="@string/surv_torch_leg" />

        <TextView
            style="@style/Content"
            android:text="@string/surv1_4" />

        <ImageView
            style="@style/Picture"
            android:src="@drawable/surv_abri" />
        <TextView
            style="@style/PicLegend"
            android:src="@string/surv_abri_leg" />

        <TextView
            style="@style/Content"
            android:text="@string/surv1_5" />

        <Button
            style="@style/SurvivalBoxNext"
            android:text="@string/surv1_next" />

    </LinearLayout>
</ScrollView>

正如您所看到的,这只是几个带有图像视图和触发加载下一个活动的按钮的文本视图。

我启动应用程序,它显示第一个屏幕。我向下滚动到按钮,点击,第二个屏幕显示(有些卡顿)。我向下滚动到按钮,点击,然后就完成了。

03-02 16:36:46.488 E/AndroidRuntime(10611): java.lang.RuntimeException: Unable to start activity ComponentInfo{net.bicou.myapp/net.bicou.myapp.SurvivalActivity}: android.view.InflateException: Binary XML file line #72: Error inflating class <unknown>
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1955)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1980)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.app.ActivityThread.access$600(ActivityThread.java:122)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1146)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.os.Handler.dispatchMessage(Handler.java:99)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.os.Looper.loop(Looper.java:137)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.app.ActivityThread.main(ActivityThread.java:4340)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at java.lang.reflect.Method.invokeNative(Native Method)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at java.lang.reflect.Method.invoke(Method.java:511)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at dalvik.system.NativeStart.main(Native Method)
03-02 16:36:46.488 E/AndroidRuntime(10611): Caused by: android.view.InflateException: Binary XML file line #72: Error inflating class <unknown>
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.view.LayoutInflater.createView(LayoutInflater.java:606)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.view.LayoutInflater.onCreateView(LayoutInflater.java:653)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:678)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.view.LayoutInflater.rInflate(LayoutInflater.java:739)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.view.LayoutInflater.rInflate(LayoutInflater.java:742)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:251)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.app.Activity.setContentView(Activity.java:1835)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at net.bicou.myapp.SurvivalActivity.onCreate(SurvivalActivity.java:34)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.app.Activity.performCreate(Activity.java:4465)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1919)
03-02 16:36:46.488 E/AndroidRuntime(10611):     ... 11 more
03-02 16:36:46.488 E/AndroidRuntime(10611): Caused by: java.lang.reflect.InvocationTargetException
03-02 16:36:46.488 E/AndroidRuntime(10611):     at java.lang.reflect.Constructor.constructNative(Native Method)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.view.LayoutInflater.createView(LayoutInflater.java:586)
03-02 16:36:46.488 E/AndroidRuntime(10611):     ... 25 more
03-02 16:36:46.488 E/AndroidRuntime(10611): Caused by: java.lang.OutOfMemoryError
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.graphics.Bitmap.nativeCreate(Native Method)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.graphics.Bitmap.createBitmap(Bitmap.java:605)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.graphics.Bitmap.createBitmap(Bitmap.java:551)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:437)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.graphics.BitmapFactory.finishDecode(BitmapFactory.java:524)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:499)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:351)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:773)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.content.res.Resources.loadDrawable(Resources.java:1937)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.widget.ImageView.<init>(ImageView.java:119)
03-02 16:36:46.488 E/AndroidRuntime(10611):     at android.widget.ImageView.<init>(ImageView.java:109)
03-02 16:36:46.488 E/AndroidRuntime(10611):     ... 28 more
03-02 16:36:46.520 W/ActivityManager(  211):   Force finishing activity net.bicou.myapp/.SurvivalActivity

我不明白:

  1. 为什么之前的活动没有被释放以腾出一些空间
  2. 为什么我的应用程序占用了如此多的堆(Grow heap (frag case) to 60.869MB for 3600016-byte allocation
  3. 我该如何连续显示包含每个约10个TextView和10个ImageView的3个活动
  4. 如果我做错了什么,因为我在我的代码中看不到任何错误,但显然有些东西出错了。

谢谢。

编辑:第一个活动的图片大小:

-rw-r--r--  1 bicou  staff   167197 29 fév 16:42 surv_abri.jpg 600x377 px
-rw-r--r--  1 bicou  staff    24658 29 fév 16:42 surv_charbon.png 559x277 px
-rw-r--r--  1 bicou  staff     5285 29 fév 16:42 surv_crafting.png 214x121 px
-rw-r--r--  1 bicou  staff     4190 29 fév 16:42 surv_hache.png 214x121 px
-rw-r--r--  1 bicou  staff     3809 29 fév 16:42 surv_pioche.png 214x121 px
-rw-r--r--  1 bicou  staff     2252 29 fév 16:42 surv_torch.png 215x121 px

第二个活动:

-rw-r--r--  1 bicou  staff     3371 29 fév 16:42 surv_four.png 204x112 px
-rw-r--r--  1 bicou  staff     5059 29 fév 16:42 surv_glass.png 215x122 px
-rw-r--r--  1 bicou  staff     3176 29 fév 16:42 surv_malle.png 204x112 px
-rw-r--r--  1 bicou  staff     2676 29 fév 16:42 surv_pelle.png 204x112 px
-rw-r--r--  1 bicou  staff   167166 29 fév 16:42 surv_repere.png 528x331 px
-rw-r--r--  1 bicou  staff   134706 29 fév 16:42 surv_sand.jpg 854x480 px

第三个活动(崩溃):

-rw-r--r--  1 bicou  staff    58919 29 fév 16:42 surv_1.jpg 600x377 px
-rw-r--r--  1 bicou  staff    51144 29 fév 16:42 surv_2.jpg 600x377 px
-rw-r--r--  1 bicou  staff    46917 29 fév 16:42 surv_3.jpg 600x377 px
-rw-r--r--  1 bicou  staff    53226 29 fév 16:42 surv_4.jpg 600x377 px
-rw-r--r--  1 bicou  staff    37787 29 fév 16:42 surv_5.jpg 600x377 px
-rw-r--r--  1 bicou  staff    31050 29 fév 16:42 surv_6.jpg 600x377 px
-rw-r--r--  1 bicou  staff    38389 29 fév 16:42 surv_7.jpg 600x377 px
-rw-r--r--  1 bicou  staff    44471 29 fév 16:42 surv_8.jpg 600x377 px

还有窗口背景:

-rw-r--r--  1 bicou  staff    30857 29 fév 16:42 background_img.png

编辑:

好的- 我尝试直接从代码中膨胀视图,以便查看是否存在错误的图像。这是我的活动代码(只有变量+ onCreate,因为其余部分相同)

private static final int[] mTitles = {
    R.string.surv1_title, R.string.surv2_title, R.string.surv3_title
};
private static final int[][] mTextViews = {
    {   R.string.surv1_1, R.string.surv1_2, R.string.surv1_3, R.string.surv1_4, R.string.surv1_5 },
    {   R.string.surv2_1, R.string.surv2_2, R.string.surv2_3, R.string.surv2_4, R.string.surv2_5, R.string.surv2_6 },
    {   R.string.surv3_1, R.string.surv3_2, R.string.surv3_3 }
};
private static final int[][] mImageViews = {
    {   R.drawable.surv_pioche, R.drawable.surv_crafting, R.drawable.surv_hache, R.drawable.surv_charbon,
        R.drawable.surv_torch, R.drawable.surv_abri },
    {   R.drawable.surv_malle, R.drawable.surv_four, R.drawable.surv_pelle, R.drawable.surv_repere,
        R.drawable.surv_sand, R.drawable.surv_glass },
    {   R.drawable.surv_1, R.drawable.surv_2, R.drawable.surv_3, R.drawable.surv_4,
        R.drawable.surv_5, R.drawable.surv_6, R.drawable.surv_7, R.drawable.surv_8  },
};
private static final int[] mNextButtons = {
    R.string.surv1_next, R.string.surv2_next, R.string.surv3_next
};

@Override
public void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    final Intent i = getIntent();
    if (savedInstanceState != null && savedInstanceState.containsKey(KEY_LAYOUT_ID)) {
        mLayoutId = savedInstanceState.getInt(KEY_LAYOUT_ID, 0);
    } else if (i != null) {
        mLayoutId = i.getIntExtra(KEY_LAYOUT_ID, 0);
    } else {
        mLayoutId = 0;
    }

    // Layout
    //setContentView(mSurvivalLayouts[mLayoutId]);
    LinearLayout ll;
    ScrollView sv;
    TextView tv;
    ImageView iv;
    Button b;

    sv = new ScrollView(this);
    sv.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
    ll = new LinearLayout(this);
    ll.setOrientation(LinearLayout.VERTICAL);
    ll.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));

    tv = new TextView(this);
    tv.setId(R.id.title);
    tv.setText(getString(mTitles[mLayoutId]));
    ll.addView(tv);

    for (final int textId: mTextViews[mLayoutId]) {
        tv = new TextView(this);
        tv.setText(getString(textId));
        ll.addView(tv);
    }

    for (final int imgId: mImageViews[mLayoutId]) {
        L.i("Creating image: "+imgId);
        iv = new ImageView(this);
        iv.setImageResource(imgId);
        ll.addView(iv);
    }

    b = new Button(this);
    b.setText(getString(mNextButtons[mLayoutId]));
    b.setId(R.id.survival_next);
    ll.addView(b);

    sv.addView(ll);
    setContentView(sv);

    // Title
    Util.setTitleFont(this, findViewById(R.id.title));

    // "Next" button
    final View nextButton = findViewById(R.id.survival_next);
    Util.setFont(this, nextButton, "Lobster.ttf");
    nextButton.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(final View v) {
            final Intent next = new Intent(SurvivalActivity.this, SurvivalActivity.class);
            next.putExtra(KEY_LAYOUT_ID, (mLayoutId + 1) % mSurvivalLayouts.length);
            startActivity(next);
            finish();
        }
    });
}

如您所见,我只是直接填充视图,并且L.i(它是Log.i(TAG, ...)的别名)指示了在任何崩溃之前最后一张被填充的ImageView。

我运行了应用程序,看到了第一个活动,然后是第二个。就像以前一样,在加载第三个活动时它崩溃了。在logcat中我看到的最后一个ID是最后一张图片R.drawable.surv_8。这是一个630x377像素,45千字节的jpeg文件。

我尝试改变视图的顺序,就像这样:

private static final int[][] mImageViews = {
    {   R.drawable.surv_pioche, R.drawable.surv_crafting, R.drawable.surv_hache, R.drawable.surv_charbon,
        R.drawable.surv_torch, R.drawable.surv_abri },
    {   R.drawable.surv_malle, R.drawable.surv_four, R.drawable.surv_pelle, R.drawable.surv_repere,
        R.drawable.surv_sand, R.drawable.surv_glass },
    {   R.drawable.surv_8, R.drawable.surv_1, R.drawable.surv_2, R.drawable.surv_3, R.drawable.surv_4,
        R.drawable.surv_5, R.drawable.surv_6, R.drawable.surv_7,  },
};

所以surv_8首先显示。应用程序仍会在最后一张图片(即R.drawable.surv_7)崩溃。因此,这不是一个图像问题。
然后我从mImageViews[2]中删除了一张图片,所以我只有7张图片而不是8张。应用程序按预期工作:活动加载时,当我点击按钮时,我进入下一个图片,当我到达最后一张时,我回到第一张。没有崩溃。
但是我可以告诉你,活动1和活动2仍会保留在内存中。确实,请查看时间:
03-04 15:47:13.685 I/ActivityManager(17430): Displayed net.bicou.myapp/.SurvivalActivity: +2s570ms
03-04 15:47:36.834 I/ActivityManager(17430): Displayed net.bicou.myapp/.SurvivalActivity: +803ms
03-04 15:47:39.756 I/ActivityManager(17430): Displayed net.bicou.myapp/.SurvivalActivity: +1s476ms
03-04 15:47:44.201 I/ActivityManager(17430): Displayed net.bicou.myapp/.SurvivalActivity: +462ms
03-04 15:47:46.717 I/ActivityManager(17430): Displayed net.bicou.myapp/.SurvivalActivity: +474ms
03-04 15:47:48.599 I/ActivityManager(17430): Displayed net.bicou.myapp/.SurvivalActivity: +474ms

加载活动仅需400毫秒,而非1.5-2.5秒。

为什么它会停留在内存中?

=> **我需要在onDestroy()手动释放所有图片吗?**

=> 您认为这个怎么样:http://androidactivity.wordpress.com/2011/09/24/solution-for-outofmemoryerror-bitmap-size-exceeds-vm-budget/
使用此解决方案,我可以全局加载大约10个位图,并在加载另一个活动时释放其中一些吗?


我强烈怀疑这是由于图像大小的原因。 - kosa
看我的修改,它们并不是很大。 - Benoit Duffez
2
@Bicou 文件大小并不是太重要,因为jpg和png都是压缩图像格式。你的图像有什么分辨率?这才是最重要的,因为它们在内存中以未压缩的形式存储。*(例如,你可以很好地压缩一个10000x10000像素的单色图像,但在内存中它仍然会变得非常大)* - user658042
@alextsc:好观点。让我编辑我的帖子。 - Benoit Duffez
3个回答

5
很抱歉,根据我在问题中给出的元素,无法回答这个问题。
实际上,正如另一个问题所提到的那样:为什么我的所有位图都被放大了200%?,我将我的图片放在drawable文件夹中,在像我的xhdpi屏幕上,这将导致Android将所有内容放大两倍(以匹配xhdpi与mdpi),并且会导致400%的内存使用量(宽度和高度增加一倍,因此像素数量增加了4倍)。
还有一件事,由于我不想让用户能够返回(请参见startActivity()后面的finish()),这是我在onPause()中添加的内容:
private void unbindDrawables(View view) {
    if (view.getBackground() != null) {
        view.getBackground().setCallback(null);
    }
    if (view instanceof ViewGroup) {
        for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
            unbindDrawables(((ViewGroup) view).getChildAt(i));
        }
        ((ViewGroup) view).removeAllViews();
    }
}

这里是我从StackOverflow中获得的一些代码(例如在这里:Drawable vs Single reusable Bitmap better with memory?)。

以下是关于此代码的我的备注,以及每一行代码的重要性:

  • setCallback(null)会移除对活动的引用,因此可以进行垃圾回收。如果不这样做,所有视图都将保留在内存中。
  • 你还需要在onPause中调用它,因为不能保证会调用onDestroy
  • 之后可能需要进行垃圾回收,以帮助GC理解某些对象的引用已变成孤立状态,可以进行垃圾回收。只需调用System.gc()即可。

这是onPause代码的结果,你的活动的主要布局的ID为top_layout

@Override
protected void onPause() {
    super.onPause();
    unbindDrawables(findViewById(R.id.top_layout));
    System.gc();
}

对于你回答的第一部分给予+1。但是根据你回答的第二部分,当我从onPause方法中调用unbidDrawables()方法并按Home键触发onPause方法后再次启动应用程序时,我的活动界面变成了空白,然后崩溃了。 - Vinay
1
我的应用程序显示了一种1-2-3教程,所以当你离开第一页时,它就消失了。这不是您的使用情况,因此您不应该这样做。 - Benoit Duffez

2
可能是你放在ImageView中的位图太大了。以下是一些你可以尝试的方法:
放弃XML布局,只需填充和显示问题ImageView或ImageViews,看看是否以这种方式出现错误。
还要检查每个图像,以查看它们实际上有多大。它们在内存中占用的大小大约是4 *宽度*高度(以字节为单位,其中宽度和高度是图像的像素大小)。
由于Bitmap实例在堆上占用内存,我想象你使用的是Android 3或更高版本。在这些版本中,Bitmap实例就像任何其他Java实例一样。在Android 2.x及以下版本中,Bitmap实例是分配在某些非堆内存中的。知道这一点后,请确保您获得的高堆使用率确实来自图像,而不是从创建很多实例的其他实例。尝试调试构造函数并查看应用程序启动/运行时谁调用了什么。
根据Bicou的观察结果,您可能希望通过BitmapFactory手动加载图像,并在此过程中通过Options对象对其进行缩小。此外,尝试通过递增实际加载到Bitmap对象中的每个图像的4 *宽度*高度来保持内存中图像字节数的计数器。

2
向下滚动堆栈跟踪的底部,您会发现实际上是在尝试为位图分配内存时抛出了 OutOfMemoryError - Benoit Duffez
1
@AndreiBodnarescu 那个说法并不完全正确。虽然在 Android 3 之前,Bitmap 不是在同一堆上分配的,但它仍然计入该堆,因此在 logcat 中看到的任何增加堆大小的数字实际上反映了已分配的 Bitmap 对象。 - devunwired
1
@Bicou 除了我的上一个评论外,这个答案大部分是正确的。当将您的 600x377 图像强制转换到内存时,每个图像的大小将不到 1MB。请注意,每个先前 Activity 中的图像也在内存中,因为那些 Activity 是 PAUSED 状态,并没有被垃圾回收,以便用户可以返回到它们。您需要在将图像加载到内存 (BitmapFactory 可帮助此类问题) 之前对其进行降采样,或者在同一 Activity 上回收图像,而不是堆叠多个图像。 - devunwired
是的,但是只要另一个活动启动,这些活动就会被finish()。所以我认为它们被垃圾回收了。 - Benoit Duffez
@AndreiBodnarescu:麻烦您看一下我编辑后的问题吗?我尝试了你建议的另一种方法。非常感谢您的支持。 - Benoit Duffez
显示剩余4条评论

1

在您的情况下,优化位图的内存使用的最佳方法是保存 ImageView 列表,在每个 ImageView 调用 finish() 之前执行此操作:

((BitmapDrawable) myImageView.getDrawable()).getBitmap().recycle();
myImageView = null;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接