【问题标题】:App is getting OOM when going to and fro from one activity to other Multiple time从一项活动到另一项活动多次往返时,应用程序出现 OOM
【发布时间】:2016-05-11 09:55:58
【问题描述】:

我有一个最简单的应用程序。其中没有繁重的编程。我有 2 项活动,例如,我要从一项活动到另一项活动来回走动 我从Activity1去Activity2,然后从Activity2回到Activity1。

通过多次执行此操作,我会收到 OOM 错误,并且当时应用程序崩溃 我不知道为什么仅通过在 Activity1 中设置背景图像和按钮而发生这种情况,而在 Activity2 中只有背景图像、图像视图和单个按钮

返回时,我也在使用 onDestroy 方法销毁 Activity2,并在 Activity1 中使用此方法,但它仍然无法让一些内存为空。

这是完整的堆栈跟踪

E/AndroidRuntime: 致命异常: main 进程:com.efu.myprojet,PID:4241 java.lang.RuntimeException:无法启动活动 ComponentInfo{com.efu.myprojet/com.efu.myprojet.MainActivity}:android.view.InflateException:二进制 XML 文件第 1 行:膨胀类错误 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2702) 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2767) 在 android.app.ActivityThread.access$900(ActivityThread.java:177) 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1449) 在 android.os.Handler.dispatchMessage(Handler.java:102) 在 android.os.Looper.loop(Looper.java:145) 在 android.app.ActivityThread.main(ActivityThread.java:5951) 在 java.lang.reflect.Method.invoke(本机方法) 在 java.lang.reflect.Method.invoke(Method.java:372) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195) 原因:android.view.InflateException:二进制 XML 文件第 1 行:膨胀类错误 在 android.view.LayoutInflater.createView(LayoutInflater.java:640) 在 com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:55) 在 android.view.LayoutInflater.onCreateView(LayoutInflater.java:689) 在 android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:748) 在 android.view.LayoutInflater.inflate(LayoutInflater.java:483) 在 android.view.LayoutInflater.inflate(LayoutInflater.java:415) 在 android.view.LayoutInflater.inflate(LayoutInflater.java:366) 在 android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:267) 在 android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:129) 在 com.efu.myprojet.MainActivity.onCreate(MainActivity.java:69) 在 android.app.Activity.performCreate(Activity.java:6289) 在 android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119) 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2655) 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2767) 在 android.app.ActivityThread.access$900(ActivityThread.java:177) 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1449) 在 android.os.Handler.dispatchMessage(Handler.java:102) 在 android.os.Looper.loop(Looper.java:145) 在 android.app.ActivityThread.main(ActivityThread.java:5951) 在 java.lang.reflect.Method.invoke(本机方法) 在 java.lang.reflect.Method.invoke(Method.java:372) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195) 引起:java.lang.reflect.InvocationTargetException 在 java.lang.reflect.Constructor.newInstance(Native Method) 在 java.lang.reflect.Constructor.newInstance(Constructor.java:288) 在 android.view.LayoutInflater.createView(LayoutInflater.java:614) 在 com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:55) 在 android.view.LayoutInflater.onCreateView(LayoutInflater.java:689) 在 android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:748) 在 android.view.LayoutInflater.inflate(LayoutInflater.java:483) 在 android.view.LayoutInflater.inflate(LayoutInflater.java:415) 在 android.view.LayoutInflater.inflate(LayoutInflater.java:366) 在 android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:267) 在 android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:129) 在 com.efu.myprojet.MainActivity.onCreate(MainActivity.java:69) 在 android.app.Activity.performCreate(Activity.java:6289) 在 android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119) 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2655) 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2767) 在 android.app.ActivityThread.access$900(ActivityThread.java:177) 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1449) 在 android.os.Handler.dispatchMessage(Handler.java:102) 在 android.os.Looper.loop(Looper.java:145) 在 android.app.ActivityThread.main(ActivityThread.java:5951) 在 java.lang.reflect.Method.invoke(本机方法) 在 java.lang.reflect.Method.invoke(Method.java:372) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195) 原因:java.lang.OutOfMemoryError:无法分配 9216012 字节分配,2044572 空闲字节和 1996KB 直到 OOM 在 dalvik.system.VMRuntime.newNonMovableArray(本机方法) 在 android.graphics.BitmapFactory.nativeDecodeAsset(本机方法) 在 android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:747) 在 android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:568) 在 android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:1014) 在 android.content.res.Resources.loadDrawableForCookie(Resources.java:3747) 在 android.content.res.Resources.loadDrawable(Resources.java:3620) 在 android.content.res.TypedArray.getDrawable(TypedArray.java:762) 在 android.view.View.(View.java:3957) 在 android.view.ViewGroup.(ViewGroup.java:507) 在 android.widget.RelativeLayout.(RelativeLayout.java:249) 在 android.widget.RelativeLayout.(RelativeLayout.java:245) 在 android.widget.RelativeLayout.(RelativeLayout.java:241) 在 java.lang.reflect.Constructor.newInstance(Native Method) 在 java.lang.reflect.Constructor.newInstance(Constructor.java:288) 在 android.view.LayoutInflater.createView(LayoutInflater.java:614) 在 com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:55) 在 android.view.LayoutInflater.onCreateView(LayoutInflater.java:689) 在 android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:748) 在 android.view.LayoutInflater.inflate(LayoutInflater.java:483) 在 android.view.LayoutInflater.inflate(LayoutInflater.java:415) 在 android.view.LayoutInflater.inflate(LayoutInflater.java:366) 在 android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:267) 在 android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:129) 在 com.efu.myprojet.MainActivity.onCreate(MainActivity.java:69) 在 android.app.Activity.performCreate(Activity.java:6289) 在 android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119) 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2655) 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2767) 在 android.app.ActivityThread.access$900(ActivityThread.java:177) 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1449) 在 android.os.Handler.dispatchMessage(Handler.java:102) 在 android.os.Looper.loop(Looper.java:145) 在 android.app.ActivityThread.main(ActivityThread.java:5951) 在 java.lang.reflect.Method.invoke(本机方法) 在 java.lang.reflect.Method.invoke(Method.java:372)

更新 1:

添加我的 xml 第一个 Activity 的 Xml

    <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.efu.myproject.FirstActivity"
    android:background="@drawable/bg_enter_the_book">


    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true"
        android:id="@+id/lLayout"
        android:padding="10dp">
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_alignParentBottom="true"
            android:background="@drawable/btn_next"
            android:onClick="EnterTheJungleBookButton"
            android:text="           "
            android:visibility="invisible"
            android:layout_marginBottom="20dp"/>
    </LinearLayout>
</RelativeLayout>

Activity2 命名为 MainActivity

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/background"
    tools:context="com.efu.myproject.MainActivity">

       <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:src="@drawable/bg_anim_name"
            android:id="@+id/iv_anim_name"/>

        <TextView
            android:id="@+id/tv_anim_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:layout_centerHorizontal="true"
            android:keepScreenOn="true"
            android:text="@string/dummy_content"
            android:textColor="#ffffff"
            android:textSize="@dimen/tv_anim_name"
            android:textStyle="bold"
            android:layout_above="@+id/tv_empty"/>
        <TextView
            android:id="@+id/tv_empty"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:layout_centerHorizontal="true"
            android:keepScreenOn="true"
            android:text="sdasdasd"
            android:visibility="invisible"
            android:textColor="#33b5e5"
            android:textSize="@dimen/tv_empty"
            android:layout_alignBaseline="@+id/iv_anim_name"
            android:layout_alignBottom="@+id/iv_anim_name"
            android:textStyle="bold"
            />
    </RelativeLayout>

    <ImageView
        android:id="@+id/iv_anim_pic"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:maxHeight="@dimen/iv_anim_pic_height"
        android:src="@drawable/ic_launcher" />

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_gravity="bottom|center_horizontal"
        android:fitsSystemWindows="true">

        <RelativeLayout
            android:id="@+id/fullscreen_content_controls"
            style="?metaButtonBarStyle"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|center_horizontal"

            android:orientation="horizontal"
            tools:ignore="UselessParent">

            <Button
                android:id="@+id/btn_next"
                style="?metaButtonBarButtonStyle"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/btn_next"
                android:layout_alignParentTop="true"
                android:layout_centerHorizontal="true" />

        </RelativeLayout>
    </FrameLayout>

</RelativeLayout>

我还有一个静态类,其中包含我的应用程序的资源,例如,我正在从该静态类中检索这些资源

ivAnimPicture.setImageResource(NextResource.getPicture(anyRandomNum));

这是我那个包含资源的类

    public class NextResource {

    static int[] animPics  =  {R.drawable.anteater,R.drawable.antelope,R.drawable.bear,
            R.drawable.bird,R.drawable.cat,R.drawable.chicken,R.drawable.cow,R.drawable.dog,
            R.drawable.duck,R.drawable.elephant,R.drawable.fox,
            R.drawable.frog,R.drawable.impala,R.drawable.lion,R.drawable.monkey,R.drawable.ostrich,
            R.drawable.panda,R.drawable.penguin,R.drawable.rabbit,
            R.drawable.sheep,R.drawable.tiger,R.drawable.vulture,R.drawable.zebra};

    static  String[] animName  = {"Anteater","Antelope","Bear","Parrot","Cat","Chicken","Cow","Dog",
            "Duck","Elephant","Fox","Frog","Impala","Lion","Monkey","Ostrich",
            "Panda","Penguin","Rabbit","Sheep","Tiger","Vulture","Zebra"};
//    public static int [] animSound = {R.raw.ballon,R.raw.billi,R.raw.carrot,
//            R.raw.fountain,R.raw.horse,R.raw.huka,R.raw.sparrow,R.raw.tea};

    public static int [] animSound = {R.raw.anteater,R.raw.antelope,R.raw.bear,
            R.raw.parrot,R.raw.cat,R.raw.chicken,R.raw.cow,R.raw.dog,
            R.raw.duck,R.raw.elephant,R.raw.fox,
            R.raw.frog,R.raw.impala,R.raw.lion,R.raw.monkey,R.raw.ostrich,
            R.raw.panda,R.raw.penguin,R.raw.fox,
            R.raw.sheep,R.raw.tiger,R.raw.vulture,R.raw.zebra};

    public static int getPicture(int i){

        return animPics[i];
    }
    public static int getSound(int i){

        return animSound[i];
    }

    public static String getName(int i){

        return animName[i];
    }
}

那我该怎么办?我的错误在哪里?

当我使用 NextResource 静态类来获取我的资源时,是否是一次又一次地获得内存而不释放内存分配的真正原因?

编辑2

@Override
protected void onDestroy() {

    if (tts != null) {
        tts.stop();//tts is Text To Speech whcih I am using 
        tts.shutdown();
    }
    ivAnimPicture = null; //this is the Imageview to show random pics
    secureRandom = null; 
    mAccelerometer = null;
    mSensorManager = null;
    mShakeDetector = null;
    tvAnimName = null;
    btnNext = null;
    random = null;
    mediaPlayer = null;
    map = null;

    super.onDestroy();

}

【问题讨论】:

  • 你能同时添加你的布局 xmls(活动 1 和活动 2)吗?
  • 是的,更新我的问题
  • “我正在使用 onDestroy 方法销毁 Activity2”是什么意思???发布您的onDestroy 方法代码。
  • 我的意思是我在 Activity2 中使用 OnDestroy 方法以便它可以释放资源
  • 令我惊讶的是,除非你在 Activity2 上做一些非常高级的事情,否则在 onDestroy 期间不需要做任何事情,恐怕你甚至可能不会打电话给super.onDestroy()。我要求查看代码的原因。 PS.:请检查我的答案,因为我相信这是您前进的方向。

标签: android android-studio out-of-memory android-studio-2.0


【解决方案1】:

根据上面发布的日志,此错误是由于您的布局中的错误膨胀而发生的。请检查您的布局一次或发布您的代码以更清晰。 或者您的活动中是否正在进行任何后台任务,您必须在其中加载任何图像?

【讨论】:

    【解决方案2】:

    你描述的是典型的内存泄漏场景。

    所以从头开始吧,如果你不知道我用谷歌搜索了内存泄漏是什么,这里的链接是我在第一个结果页面上可以找到的最漂亮的插图:http://www.programcreek.com/2013/10/the-introduction-of-memory-leak-what-why-and-how/

    不幸的是,内存泄漏可能在任何地方发生,即使您将整个项目分享给我们,大多数人也不会费心阅读它,因为查找内存泄漏实在是太无聊了。

    说有方法和工具可以帮到你:

    • 内存监视器。第一件事。您应该使用 Android Studio 上的内存监视器来检查它是否真的是内存泄漏。当内存增长到一个新的活动时,你会看到它发生,并且从它回来时它不会减少。

    • LeakCanary 来救援。广场上的人做了这个很棒的库来自动检测内存泄漏https://github.com/square/leakcanary 它本身并不能完成所有工作,但是正如您指出的 Activity,它应该非常简单。只需按照他们自述文件中的内容进行操作即可。

    这应该让你开始。编码愉快。

    编辑:

    从您的onDestroy 代码中,我可以看到您正在使用加速度计、传感器管理器、抖动检测器和媒体播放器。这些都是可以引用活动并泄漏它的东西。只是调用null 并不意味着对方没有持有你的活动。

    所以所有这一切都强化了我原来的答案:了解内存泄漏,检查内存监视器并使用泄漏金丝雀。

    【讨论】:

    • 那么我怎样才能取消引用它们?我的意思是如果我将它们设置为 null 那么为什么内存没有清理?或者我应该怎么做
    • 查看这些类的方法,例如:removeListenersetListener(null) 或某种类型的 stopclean up。它们可以很容易地挂接到框架级别,并且在您创建它们并将 setLister 设置为您的活动时仍然保持对您的活动的引用。但这一切都是推测,你真的应该使用 LeakCanary 来获取详细的数据。
    • 我不知道如何使用它,请您指导我如何使用 LeakCanary
    • 如果您的意思是在它在您的应用程序上运行后实际使用它,那么......打开应用程序,执行您知道会导致内存泄漏的事情(在您的情况下输入活动 2,然后从它)。然后等待几秒钟,因为 LeakCanary 操作超时
    【解决方案3】:

    缩小背景图片大小。可能是您使用的图像太大。请参考thisthis

    【讨论】:

    • 我正在使用的设备是 S4 xxhdpi ,所以我有相应的图像,即 1200*1920 ,,,
    • 我说的是图像大小而不是宽度和高度。如果您想检查,请删除您的图像并检查您的应用程序是否收到 OOM?
    • 你的意思是我应该压缩我的图片?
    • 是的,你应该压缩你的图片。
    • 我已经使用 Tinypng 网站完成了这项工作。我也在更新我的问题,请查看
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-19
    相关资源
    最近更新 更多