Повторное создание деятельности

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

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

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

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

Примечание: Для того, чтобы Android система восстановила состояние представлений в вашей деятельности, каждое представление должно иметь уникальный идентификатор, задаваемый в android:id атрибуте.

Чтобы сохранить дополнительные данные о состоянии деятельности, необходимо перегрузить onSaveInstanceState() метод обратного вызова. Система вызывает этот метод, когда пользователь покидает вашу деятельность, и передает в него Bundle объект, который будет сохранен в том случае, если ваша деятельность будет неожиданно разрушена. Если система должна восстановить экземпляр деятельности позже, он передает тот же Bundle объект в оба onRestoreInstanceState() и onCreate() метода.

Рисунок 2. Поскольку система начинает останавливать вашу деятельность, она вызывает onSaveInstanceState() (1), вы можете указать дополнительные данные о состоянии, которые вы хотели бы сохранить в случае, когда Activity экземпляр должен быть создан заново. Если деятельность разрушается и такой же экземпляр должен быть создан заново, система передает данные состояния определённые в (1) как в onCreate() метод (2), так и onRestoreInstanceState() метод (3).

Сохранение состояния вашей деятельности

Когда ваша деятельность начинает останавливаться, система вызывает onSaveInstanceState() , так что ваша деятельность может сохранить информацию о состоянии в виде коллекции пар ключ-значение. Реализация по умолчанию этого метода сохраняет информацию о состоянии представлений иерархии деятельности, таких как текст из EditText виджета или положение прокрутки ListView.

Чтобы сохранить дополнительную информацию о состоянии для вашей деятельности, вы должны реализовать onSaveInstanceState() и добавить пары ключ-значение в Bundle объект. Например:

static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
...

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // Save the user's current game state
    savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
    savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);
    
    // Always call the superclass so it can save the view hierarchy state
    super.onSaveInstanceState(savedInstanceState);
}

Внимание: Всегда вызывайте реализацию родительского класса onSaveInstanceState() , чтобы реализация по умолчанию смогла сохранить состояние представлений иерархии.

Восстановить состояние вашей деятельности

Когда ваша деятельность воссоздана после того, как была ранее уничтожена, вы можете восстановить сохраненное состояние из Bundle , который система передает в вашу деятельность. Оба onCreate() и onRestoreInstanceState() метода обратного вызова получат то же самый Bundle , который содержит информацию состояния экземпляра.

Поскольку onCreate() метод вызывается, когда система создается новый экземпляр вашей деятельности и когда воссоздает предыдущий, вы должны проверить, равен ли Bundle состояния null, прежде чем пытаться прочитать его. Если он равен null, то система создает новый экземпляр деятельности, вместо восстановления предыдущего, который был разрушен.

Например, вот как можно восстановить некоторые данные состояния в onCreate():

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState); // Always call the superclass first
   
    // Check whether we're recreating a previously destroyed instance
    if (savedInstanceState != null) {
        // Restore value of members from saved state
        mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
        mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
    } else {
        // Probably initialize members with default values for a new instance
    }
    ...
}

Вместо восстановления состояния во время выполнения onCreate() вы можете реализовать onRestoreInstanceState(), которой система вызывает после onStart() метода. Система вызывает onRestoreInstanceState() только если есть сохраненное состояние для восстановления, так что вам не нужно проверять, равен ли Bundle значению null:

public void onRestoreInstanceState(Bundle savedInstanceState) {
    // Always call the superclass so it can restore the view hierarchy
    super.onRestoreInstanceState(savedInstanceState);
   
    // Restore state members from saved instance
    mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
    mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}

Внимание: Всегда вызывайте реализацию родительского класса onRestoreInstanceState() , чтобы реализация по умолчанию могла восстановить состояние представлений иерархии.

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