Приложение получает OOM при переходе от одного действия к другому несколько раз

У меня есть самое простое приложение. в котором нет тяжелого программирования. У меня есть 2 действия, и я перехожу от одного действия к другому, например, я перехожу к действию 2 из действия 1, а затем возвращаюсь к действию 1 из действия 2.

Делая это несколько раз, я получаю ошибку OOM, и в это время происходит сбой приложения. Я понятия не имею, почему это происходит, просто устанавливая фоновое изображение и кнопку в Activity1, а в Activity2 есть только фоновое изображение, а также представление изображения и одна кнопка

Возвращаясь назад, я уничтожаю Activity2, используя метод onDestroy, и использую этот метод также в Activity1, но он все еще не работает, чтобы освободить память.

Вот полная трассировка стека

Обновление 1:

Добавление моих XML-файлов Xml первого действия

Activity2 с именем MainActivity

    <?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>

Также у меня есть статический класс, который содержит ресурсы моего приложения, и я извлекаю эти ресурсы, например, из этого статического класса.

    <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 Static для извлечения своих ресурсов, является ли это реальной причиной получения памяти снова и снова, а не освобождения памяти?

Изменить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();

}

person Coas Mckey    schedule 11.05.2016    source источник
comment
да, обновляю мой вопрос   -  person Droidekas    schedule 11.05.2016
comment
что вы имеете в виду, говоря, что я уничтожаю Activity2, используя метод onDestroy??? Опубликуйте свой код метода _1_.   -  person Coas Mckey    schedule 11.05.2016
comment
Я имею в виду, что использую метод OnDestroy в Activity2, чтобы он мог освободить ресурсы.   -  person Budius    schedule 11.05.2016
comment
и мое удивление заключается в том, что если вы не делаете довольно сложные вещи в Activity2, вам не нужно ничего делать во время onDestroy, и я боюсь, что вы можете даже не вызывать _1_. Причина, по которой я попросил показать код. PS: проверьте мой ответ, так как я уверен, что это ваш путь вперед.   -  person Coas Mckey    schedule 11.05.2016
comment
позвольте мне добавить, что и при уничтожении тоже   -  person Budius    schedule 11.05.2016
comment
Я добавил OnDestroy   -  person Coas Mckey    schedule 11.05.2016
comment
и я добавил еще кое-что в свой первоначальный ответ. Однозначного ответа нет, и вам придется копать глубже самостоятельно. Но воспринимайте это как отличный обучающий момент, который научит вас многому об опасностях сборщика мусора.   -  person Coas Mckey    schedule 11.05.2016
comment
так как я могу unreference их? Я имею в виду, если я устанавливаю для них значение null, то почему память не очищается? Или что еще я должен сделать   -  person Budius    schedule 11.05.2016


Ответы (3)


То, что вы описываете, является классическим сценарием утечки памяти.

person Abhilasha Sharma    schedule 11.05.2016

Итак, начните с самого начала, если вы не знаете, что такое утечка памяти, я погуглил об этом, и вот ссылка на самую красивую иллюстрацию, которую я смог найти на первой странице результатов: http://www.programcreek.com/2013/10/the-introduction-of-memory-leak-what-why-and-how/

К сожалению, утечки памяти могут произойти где угодно, и даже если вы поделитесь с нами своим полным проектом, большинство не удосужится его прочитать, потому что поиск утечек памяти чертовски скучен.

Сказал, что есть методы и инструменты, которые помогут вам:

монитор памяти. Первые вещи. Вы должны использовать монитор памяти в Android Studio, чтобы убедиться, что это действительно утечка памяти. Вы увидите, как это происходит, когда память увеличивается при переходе к новой деятельности и не уменьшается при возвращении из нее.

  • LeakCanary спешит на помощь. Ребята из Square сделали эту замечательную библиотеку для автоматического обнаружения утечек памяти https://github.com/square/leakcanary он не выполняет ВСЮ работу сам по себе, но, как вы указываете Activity, он должен быть довольно простым. Просто следуйте тому, что написано в их файле readme.

  • Это должно помочь вам начать. Удачного кодирования.

изменить:

из вашего кода onDestroy я вижу, что вы используете акселерометр, диспетчер датчиков, детектор тряски и медиаплеер. Это все вещи, которые могут иметь отношение к активности и быть ее утечкой. Просто звонок null не означает, что другая сторона не сдерживает вашу активность.

Так что все это только подтверждает мой первоначальный ответ: узнайте об утечках памяти, проверьте монитор памяти и используйте канареечную утечку.

Уменьшите размер фонового изображения. Возможно, вы используете слишком большое изображение. См. это и это.

person Budius    schedule 11.05.2016
comment
посмотрите на эти классы для таких методов, как: _1_ или _2_ или какой-то тип _3_ или _4_. Их можно очень легко подключить на уровне фреймворка, и они по-прежнему будут ссылаться на вашу деятельность, когда вы их создали, и установитеLister в качестве своей деятельности. Но все это предположения, вам действительно следует использовать LeakCanary для получения подробных данных. - person Coas Mckey; 11.05.2016
comment
Я не понимаю, как его использовать, не могли бы вы подсказать мне, как я могу использовать LeakCanary - person Budius; 11.05.2016
comment
если вы имеете в виду на самом деле использовать его после того, как он запущен в вашем приложении, ну... откройте приложение, сделайте то, что, как вы знаете, приведет к утечке памяти (в вашем случае введите действие 2, а затем вернитесь из него). Затем вы ждете несколько секунд, пока LeakCanary работает по тайм-ауту. - person Coas Mckey; 11.05.2016
comment
Давайте продолжим обсуждение в чате. - person Budius; 11.05.2016
comment
Я пробовал, чтобы LeakCananry создал дамп в следующем каталоге I/art: hprof: heap dump /storage/emulated/0/Download/leakcanary-com.efu.myproject/suspected_leak_heapdump.hprof, начиная... 05-11 16 :26:32.466 25469-26098/com.efu.myproject I/art: hprof: создание дампа кучи (77 МБ) за 4,701 с - person Coas Mckey; 11.05.2016
comment
Теперь в панели запуска приложений вашего устройства должно быть приложение Leak Canary. Он показывает вам трассировку утечки в приятном пользовательском интерфейсе. - person Coas Mckey; 11.05.2016
comment
что ты имеешь в виду, я не получил это в лаунчере? - person Budius; 11.05.2016
comment
Устройство, с которым я работаю, - это S4 xxhdpi , поэтому у меня есть изображение соответственно, т.е. 1200 * 1920 ,,, - person Coas Mckey; 11.05.2016

можете ли вы добавить оба макета xmls (действие 1 и действие 2)?

person Bhavin Shah    schedule 11.05.2016
comment
Я говорю о размере изображения, а не о ширине и высоте. Если вы хотите проверить, пожалуйста, удалите свое изображение и проверьте свое приложение, получаете ли вы OOM или нет? - person Coas Mckey; 11.05.2016
comment
Вы имеете в виду, что я должен сжимать свои изображения? - person Bhavin Shah; 11.05.2016
comment
Да, вы должны сжать изображение. - person Coas Mckey; 11.05.2016
comment
Я уже сделал это с помощью веб-сайта Tinypng. Я также обновляю свой вопрос, пожалуйста, просмотрите его - person Bhavin Shah; 11.05.2016
comment
E/AndroidRuntime: НЕИСПРАВНОЕ ИСКЛЮЧЕНИЕ: основной процесс: 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$Met hodAndArgsCaller.run(ZygoteInit.java:1400) в com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195) Вызвано: android.view.InflateException: строка двоичного XML-файла № 1: ошибка раздувания класса в android .Посмотреть. 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(Native Method) на 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(собственный метод) в 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) на ndroid.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 свободных байт и 1996 КБ до 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) t 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(собственный метод) в 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.createV iewFromTag(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(ActivityThre ad.java:5951) на java.lang.reflect.Method.invoke(собственный метод) на java.lang.reflect.Method.invoke(Method.java:372) - person Coas Mckey; 11.05.2016