Подтвердить что ты не робот

OnPause() и onStop() в действии

Я новичок в разработке Android, и я все еще не могу понять onPause() и onStop() в onStop().

В моем приложении у меня есть статический класс, который я называю Counter, и он сохраняет состояние переменных в памяти для приложения. Мое приложение отлично работает в эмуляторе. То, что я пытался проверить, было дифференциальное поведение onPause() сравнению с onStop().

Для onPause я хотел, чтобы значения, хранящиеся в элементах класса Counter, сохранялись, а вызов onStop() я хотел, чтобы значения счетчика были сброшены на ноль. Поэтому я переопределяю onStop() и устанавливаю переменные внутри класса счетчика равными нулю. Однако в эмуляторе я не могу получить приложение в состоянии Paused. В эмуляторе я открываю свое приложение, осуществляю его. Затем я нажимаю кнопку "домой" (а не кнопку "Назад") эмулятора и запускаю другое приложение, полагая, что это будет имитировать onPause(). Тем не менее, эмулятор, похоже, не соблюдает это (я использую эмулятор armeabi v7a), он всегда вызывает onStop() потому что мои значения счетчиков все возвращаются к нулю, за мое переопределение в onStop(). Является ли это неотъемлемым элементом эмулятора, или я делаю что-то неправильно, чтобы заставить свою деятельность в состоянии паузы?

4b9b3361

Ответ 1

Я не уверен, с каким эмулятором вы тестируете, но onPause - это тот метод, который всегда гарантированно вызывается, когда ваш Activity теряет фокус (и я говорю всегда, потому что на некоторых устройствах, Android 3.2+, onStop не всегда гарантированно вызывается до того, как Activity будет уничтожен).

Хороший способ понять жизненный цикл Activity для новичков - это заманить ваши переопределенные методы с помощью Log s. Например:

public class SampleActivity extends Activity {

    /**
     * A string constant to use in calls to the "log" methods. Its
     * value is often given by the name of the class, as this will 
     * allow you to easily determine where log methods are coming
     * from when you analyze your logcat output.
     */
    private static final String TAG = "SampleActivity";

    /**
     * Toggle this boolean constant value to turn on/off logging
     * within the class. 
     */
    private static final boolean VERBOSE = true;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (VERBOSE) Log.v(TAG, "+++ ON CREATE +++");
    }

    @Override
    public void onStart() {
        super.onStart();
        if (VERBOSE) Log.v(TAG, "++ ON START ++");
    }

   @Override
    public void onResume() {
        super.onResume();
        if (VERBOSE) Log.v(TAG, "+ ON RESUME +");
    }

    @Override
    public void onPause() {
        super.onPause();
        if (VERBOSE) Log.v(TAG, "- ON PAUSE -");
    }

    @Override
    public void onStop() {
        super.onStop();
        if (VERBOSE) Log.v(TAG, "-- ON STOP --");
    }

   @Override
    public void onDestroy() {
        super.onDestroy();
        if (VERBOSE) Log.v(TAG, "- ON DESTROY -");
    }
}

Ответ 2

Я знаю, что ваш вопрос был 6 месяцев назад, но если кто-то еще споткнется на этот вопрос:

Я делаю что-то неправильно, чтобы заставить свою деятельность в приостановленное состояние.

Да, вы. Это:

Я нажал кнопку "домой" (а не кнопку "Назад" ) эмулятора и запустите другое приложение, полагая, что это будет имитировать onPause() деятельность.

Нажатие кнопки "домой" действительно вызовет метод onPause(), но поскольку кнопка "home" делает вашу активность более не видимой, она вызовет метод onStop() (например, упомянутый патриот и milter).

В соответствии с инструкцией разработчика Activities (http://developer.android.com/guide/components/activities.html) вы можете отобразить диалоговое окно или просто перевести устройство в режим сна.

В качестве альтернативы вы вызываете действие, которое будет лишь частично препятствовать вызывающей активности. Поэтому вызовите операцию, которая создает окно с видом размера:

 android:layout_width="100dp"
 android:layout_height="100dp"

который не охватывает весь экран, тем самым оставляя вызывающую активность частично видимой, тем самым вызывая метод вызова только onPause().

Клонировать эту активность так, чтобы оба размера представления были "match_parent" вместо "100dp" и вызывают его, и вызовы методов onPause() и onStop() вызывающей активности будут вызваны, потому что вызывающая активность не будет видна.

Конечно, могут быть исключения, например, если вызываемая активность вызывает сбой приложения в любом из его onCreate(), onStart() или onResume(), тогда onStop() вызывающей активности не будет вызываться, Я просто говорю об общем случае здесь.

Ответ 3

Различия между вызовами onPause() и onStop() могут быть довольно тонкими. Однако, как объяснено здесь, onPause() обычно выполняется, когда другое действие фокусируется (возможно, как всплывающее окно или прозрачное окно), в то время как текущая активность все еще работает. Если вы полностью удаляетесь от приложения (например, нажав кнопку "домой" ), действие больше не отображается и система может выполнять onStop(). Я могу сказать только потому, что, как сказал Алекс, есть случаи, когда onStop не вызывается до того, как действие уничтожено.

Ответ 4

OnPause():

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

OnStop():

"Если действие полностью закрыто другим действием, оно остановлено. Оно по-прежнему сохраняет всю информацию о состоянии и члене, однако оно больше не отображается пользователю, поэтому его окно скрыто, и оно часто будет убито когда требуется память в другом месте".

Взято из класса активности ссылки на Android: http://developer.android.com/reference/android/app/Activity.html

Ответ 5

Если вы эмулируете Android 4.x, вы можете контролировать, как система обрабатывает фоновые действия, используя "Настройки" → "Параметры разработчика" → "Не выполнять действия и префикс фонового процесса". Для более старых версий есть приложение Dev Tools, которое содержит те же настройки. Однако в условиях низкой памяти система может игнорировать эти настройки и прекратить работу приложения. Увеличение объема памяти, назначенного эмулятору, может помочь.

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

Ответ 6

Я согласен с milter!

OnPause():

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

Если вы меняете приложения без нажатия клавиши "Назад" (нажмите и удерживайте кнопку "HOME" ), тогда ОС будет вызывать onPause. Когда вы вернетесь в свою деятельность (нажмите и снова удерживайте ДОМЕН) в onResume вы должны сохранить все ваши личные переменные. Но вы не можете управлять пользователем, верно?!

если вы ожидаете, что пользователь покинет ваше приложение, а ОС вызовет ваш onStop, вы лучше сохраните свои данные, если вы намереваетесь вернуться туда, где вы остановились.

У меня тоже есть Timer, мне нужно сохранить прошедшее время, поэтому, когда пользователь вернется, я могу восстановить данные. вот мой пример для сохранения:

@Override 
public void onSaveInstanceState(Bundle savedInstanceState) { 
  super.onSaveInstanceState(savedInstanceState); 
  // Save UI state changes to the savedInstanceState. 
  // This bundle will be passed to onCreate if the process is 
  // killed and restarted. 

  savedInstanceState.putLong("elapsedTime", elapsedTime);
  // etc. 
} 

И мой код для восстановления:

@Override 
public void onRestoreInstanceState(Bundle savedInstanceState) { 
  super.onRestoreInstanceState(savedInstanceState); 
  // Restore UI state from the savedInstanceState. 
  // This bundle has also been passed to onCreate. 

  elapsedTime = savedInstanceState.getLong("elapsedTime");
} 

Поместите эти методы внутри своего класса, и вы хорошо пойдете. Имейте в виду, что строка "elapsedTime" в моем случае является ключом к системе и должна быть уникальной. Используйте уникальные строки для каждой части данных, которую вы хотите сохранить. Например, "startClock", "ClockTextColor" и т.д.