Перезапуск активности при ротации Android - PullRequest
1307 голосов
/ 19 января 2009

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

  1. Поместите все начальные настройки в другую функцию, чтобы они не терялись при повороте устройства или
  2. Сделайте так, чтобы onCreate больше не вызывался, а раскладка просто настраивалась или
  3. Ограничьте приложение только портретом, чтобы onCreate не вызывался.

Ответы [ 31 ]

936 голосов
/ 19 января 2009

Использование класса приложения

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

public class MyApplicationClass extends Application {
  @Override
  public void onCreate() {
    super.onCreate();
    // TODO Put your application initialization code here.
  }
}

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

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

ПРИМЕЧАНИЕ. Вам нужно будет указать имя вашего нового класса приложения в манифесте для его регистрации и использования:

<application
    android:name="com.you.yourapp.MyApplicationClass"

Реакция на изменения конфигурации [ОБНОВЛЕНИЕ: устарело с API 13; см. Рекомендуемую альтернативу ]

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

Начните с добавления узла android:configChanges в узел манифеста вашей деятельности

 <activity android:name=".MyActivity"
      android:configChanges="orientation|keyboardHidden"
      android:label="@string/app_name">

или для Android 3.2 (уровень API 13) и новее :

<activity android:name=".MyActivity"
      android:configChanges="keyboardHidden|orientation|screenSize"
      android:label="@string/app_name">

Затем в Activity переопределите метод onConfigurationChanged и вызовите setContentView, чтобы принудительно сделать макет графического интерфейса в новой ориентации.

@Override
public void onConfigurationChanged(Configuration newConfig) {
  super.onConfigurationChanged(newConfig);
  setContentView(R.layout.myLayout);
}
182 голосов
/ 04 марта 2012

Обновление для Android 3.2 и выше:

Внимание : Начиная с Android 3.2 (уровень API 13), «размер экрана» также изменяется , когда устройство переключается между книжной и альбомной ориентацией. Таким образом, если вы хотите предотвратить перезапуск среды выполнения из-за изменения ориентации при разработке для API уровня 13 или выше (как заявлено атрибутами minSdkVersion и targetSdkVersion), вы должны включить значение "screenSize" в дополнение к значению "orientation". То есть вы должны объявить android:configChanges="orientation|screenSize". Однако, если ваше приложение предназначено для уровня API 12 или ниже, то ваша активность всегда сама обрабатывает это изменение конфигурации (это изменение конфигурации не перезапускает вашу активность, даже при работе на устройстве Android 3.2 или выше).

118 голосов
/ 05 августа 2012

Вместо того, чтобы пытаться полностью исключить запуск onCreate(), возможно, попробуйте проверить, передается ли Bundle savedInstanceState в событие, чтобы узнать, является ли оно нулевым или нет.

Например, если у меня есть какая-то логика, которая должна запускаться, когда Activity действительно создается, а не при каждом изменении ориентации, я запускаю эту логику в onCreate(), только если savedInstanceState равно нулю.

В противном случае я все еще хочу, чтобы макет правильно перерисовывался для ориентации.

public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_game_list);

        if(savedInstanceState == null){
            setupCloudMessaging();
        }
}

не уверен, что это окончательный ответ, но он работает для меня.

95 голосов
/ 04 января 2011

что я сделал ...

в манифесте, в раздел действий добавлено:

android:configChanges="keyboardHidden|orientation"

в коде для активности, реализовано:

//used in onCreate() and onConfigurationChanged() to set up the UI elements
public void InitializeUI()
{
    //get views from ID's
    this.textViewHeaderMainMessage = (TextView) this.findViewById(R.id.TextViewHeaderMainMessage);

    //etc... hook up click listeners, whatever you need from the Views
}

//Called when the activity is first created.
@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    InitializeUI();
}

//this is called when the screen rotates.
// (onCreate is no longer called when screen rotates due to manifest, see: android:configChanges)
@Override
public void onConfigurationChanged(Configuration newConfig)
{
    super.onConfigurationChanged(newConfig);
    setContentView(R.layout.main);

    InitializeUI();
}
64 голосов
/ 19 января 2009

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

android:configChanges

в манифест, а затем изменения, которые вы хотите обработать. Так что для ориентации вы бы использовали:

android:configChanges="orientation"

и для открытия или закрытия клавиатуры вы должны использовать:

android:configChanges="keyboardHidden"

Если вы хотите работать с обоими, вы можете просто разделить их командой pipe, как:

android:configChanges="keyboardHidden|orientation"

Это вызовет метод onConfigurationChanged в любой операции, которую вы вызываете. Если вы переопределите метод, вы можете передать новые значения.

Надеюсь, это поможет.

41 голосов
/ 23 декабря 2010

Я только что открыл это знание:

Для сохранения активности через изменение ориентации и обработки с помощью onConfigurationChanged, документации и приведенный выше пример кода предлагает это в файле манифеста:

<activity android:name=".MyActivity"
      android:configChanges="orientation|keyboardHidden"
      android:label="@string/app_name">

, что дает дополнительное преимущество:

Суть в том, что пропуск keyboardHidden может показаться логичным, но это вызывает сбои в эмуляторе (по крайней мере для Android 2.1): указание только orientation заставит эмулятор вызывать как OnCreate, так и onConfigurationChanged иногда и только OnCreate другие времена.

Я не видел сбоя на устройстве, но слышал о сбое эмулятора для других. Так что стоит документировать.

35 голосов
/ 22 сентября 2011

Возможно, вы также рассмотрите возможность использования платформы Android для сохранения данных при изменении ориентации: onRetainNonConfigurationInstance() и getLastNonConfigurationInstance().

Это позволяет вам сохранять данные при изменениях конфигурации, такие как информация, которую вы, возможно, получили из выборки сервера, или что-то еще, что было вычислено в onCreate или более поздней версии, в то же время позволяя Android изменять макет Activity с помощью XML-файл для ориентации в настоящее время используется.

См. здесь или здесь .

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

30 голосов
/ 21 сентября 2012

Этот подход полезен, но не является полным при использовании фрагментов.

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

setRetainInstance(true); в конструкторе (ах) фрагмента

Это приведет к тому, что фрагменты будут сохранены во время изменения конфигурации.

http://developer.android.com/reference/android/app/Fragment.html#setRetainInstance(boolean)

23 голосов
/ 09 августа 2012

Я просто добавил

     android:configChanges="keyboard|keyboardHidden|orientation"

в файле манифеста и не добавили любой onConfigurationChanged метод в мою деятельность.

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

16 голосов
/ 21 января 2010

Метод onCreate по-прежнему вызывается даже при изменении orientation Android. Таким образом, перенос всех тяжелых функций на этот метод не поможет вам

...