Приложение Android аварийно завершает работу при очистке оперативной памяти

У меня есть приложение, которое вылетает после очистки оперативной памяти. Я не могу использовать onSavedInstanceState из-за текущей реализации. Итак, кто-нибудь знает, как я могу просто перезапустить приложение, когда пользователь пытается открыть его из последних приложений? Я уже пробовал этот код в основном действии, которое является базовым классом для всех действий:

if (isFirstApplicationStartUp()) {
        Intent i = new Intent(this, Main.class);
        startActivity(i);
    }

isFirstApplicationStartUp() — это логическое значение, установленное в true из класса, который расширяет Application (в onCreate).

Но эта реализация не работает так, как хотелось бы, поскольку предыдущие действия вызываются до выполнения этого кода.


person Laura    schedule 03.12.2014    source источник
comment
он падает в точной строке?   -  person MineConsulting SRL    schedule 03.12.2014
comment
почему бы вам не опубликовать трассировку стека, чтобы мы знали, в чем ошибка, и исправляли ее таким образом, вместо того, чтобы пытаться взломать ваш путь вокруг вещей   -  person tyczj    schedule 03.12.2014
comment
другие приложения тоже вылетают при очистке памяти?   -  person Sarthak Mittal    schedule 03.12.2014
comment
И вы действительно не можете реализовать его таким образом, чтобы он работал без каких-либо настроек при первом запуске? Все остальное кодирование было бы обходным путем.   -  person Wicked161089    schedule 03.12.2014
comment
Если для переменной boolean установлено значение true в onCreate() класса Application вашего приложения, то она всегда будет иметь значение true. Потому что этот метод всегда вызывается перед созданием любых действий вашего приложения.   -  person David Wasser    schedule 03.12.2014
comment
Я не публиковал трассировку стека, потому что это не имеет значения. Все объекты становятся нулевыми. Таким образом, приложение вылетает, где бы я ни находился в приложении. Переменная не всегда имеет значение true. Я установил его в false в коде, где это необходимо. Но мне нужен другой подход, поскольку с текущим я должен проверять каждый объект на нуль.   -  person Laura    schedule 04.12.2014


Ответы (3)


Вы, вероятно, не хотите, чтобы приложение перезапускалось с самого начала при запуске из списка недавних задач, потому что ваше приложение может вполне работать. Что вам нужно сделать, так это помнить, было ли ваше приложение правильно инициализировано (что бы это ни значило). Если пользователь возвращается в ваше приложение, а процесс был завершен и перезапущен с момента инициализации вашего приложения, вам необходимо обнаружить это условие, а затем перенаправить пользователя обратно к первому действию вашего приложения.

Лучший способ сделать это — иметь базовый класс для всех ваших действий. В этом базовом классе вы реализуете код в onCreate(), который проверяет, правильно ли инициализировано ваше приложение. Если он не был должным образом инициализирован, вы должны перенаправить пользователя обратно к первому действию. Что-то вроде этого:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Check if the application has been restarted by AndroidOS after it has killed the process due to inactivity
    //  in this case, we need to redirect to the first activity and dump all other activities in the task stack
    //  to make sure that the application is properly initialized
    if (!isApplicationInitialized() && !(this instanceof FirstActivity)) {
        Intent firstIntent = new Intent(this, FirstActivity.class);

        firstIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // So all other activities will be dumped
        startActivity(firstIntent);

        // We are done, so finish this activity and get out now
        finish();
        return;
    }

    // Now call the activity-specific onCreate()
    doOnCreate(savedInstanceState);

Все ваши действия должны наследоваться от этого базового класса, и они НЕ должны переопределять onCreate(). Вместо этого им следует реализовать метод doOnCreate(), который будет вызываться из базового класса onCreate() (см. выше).

ПРИМЕЧАНИЕ. Это работает только в том случае, если корневая активность (в этом примере FirstActivity) никогда не завершается до закрытия приложения. Это означает, что у вас всегда будет экземпляр FirstActivity в корне вашей задачи. Это необходимо для корректной работы Intent.FLAG_ACTIVITY_CLEAR_TOP.

(ду дах)

person David Wasser    schedule 03.12.2014
comment
Это работает. Большое спасибо за ваш ответ, вы спасли мой день! - person Laura; 04.12.2014
comment
Все ваши действия должны наследоваться от этого базового класса, и они НЕ должны переопределять onCreate(). Вместо этого им следует реализовать метод doOnCreate(), который будет вызываться из базового класса onCreate() (см. выше). Почему они не могут переопределить onCreate базовой активности? - person WPMed; 01.12.2017
comment
Это потому, что даже если я вызову функцию завершения в базовой активности, onCreate производной активности все равно будет выполняться? - person WPMed; 01.12.2017
comment
@WPMed Если вы переопределите onCreate(), вам нужно будет позвонить super.onCreate(). Если метод в базовом классе решит, что ему нужно перенаправить на FirstActivity, ваш onCreate() не узнает об этом и может натворить глупостей. Это решение более чистое. В случае, когда onCreate() перенаправляет на FirstActivity, ваш doOnCreate() никогда не будет вызван. - person David Wasser; 01.12.2017
comment
Хорошо, теперь я понимаю. Да, это очень чистый дизайн, спасибо! - person WPMed; 01.12.2017
comment
@DavidWasser Извините, я случайно проголосовал за это. Если вы сделаете редактирование, я могу отменить - person MSpeed; 04.12.2020
comment
@MSpeed ​​Спасибо за комментарий. Мне было интересно, почему за это проголосовали. Я отредактировал ответ, так что, возможно, вы сможете это исправить. - person David Wasser; 04.12.2020
comment
Сделано и проголосовали за неудобства! :) хаха - person MSpeed; 04.12.2020

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

Вот более подробное объяснение: http://www.senzumbrellas.com/collection/home.php?sl=en

По умолчанию система использует состояние экземпляра Bundle для сохранения информации о каждом объекте View в макете действия (например, текстовое значение, введенное в объект EditText). Итак, если ваш экземпляр активности уничтожен и воссоздан, состояние макета восстанавливается до его предыдущего состояния без необходимости кода. Однако у вашей активности может быть дополнительная информация о состоянии, которую вы хотели бы восстановить, например переменные-члены, которые отслеживают ход выполнения пользователем действия.


Вместо установки этого логического значения Android предоставляет вам способ доступа к любой информации об экземпляре. Вместо этого вы должны переопределить onSaveInstanceState (Bundle saveInstanceState):

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    //save any state variables you want to keep around.
    //this is not rally meant for large memory intensive objects like images

    super.onSaveInstanceState(savedInstanceState);
}

Затем в onCreate проверьте saveInstanceState в onCreate:

if(savedInstanceState != null)
{
    //this means that the activity is being restored
}
person toidiu    schedule 03.12.2014
comment
Зонтики Сенз? - person MSpeed; 27.11.2020

используйте общие переменные вместо глобальных переменных в действиях. Это решило мою проблему.

person Shil    schedule 29.10.2015