Перезапуск активности при ротации Android

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

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

В это сообщение в блоге есть довольно полное объяснение того, как сохранить долго выполняющиеся асинхронные задачи при изменении конфигурации активности!

Adrian Monk 16.01.2014 00:14

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

Snicolas 24.08.2014 04:36
1 417
2
391 761
33
Перейти к ответу Данный вопрос помечен как решенный

Ответы 33

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

android:configChanges

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

android:configChanges = "orientation"

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

android:configChanges = "keyboardHidden"

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

android:configChanges = "keyboardHidden|orientation"

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

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

@GregD Я знаю, поэтому сейчас хорошее время обновить его, чтобы отразить сегодняшнюю ситуацию. Учитывая количество голосов за этот вопрос, на него по-прежнему ссылаются из других вопросов по SO.

Simon Forsberg 07.11.2013 03:12
Ответ принят как подходящий

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

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

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

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

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

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

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

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

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

Начните с добавления узла 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, чтобы заставить макет GUI быть переделан в новой ориентации.

@Override
public void onConfigurationChanged(Configuration newConfig) {
  super.onConfigurationChanged(newConfig);
  setContentView(R.layout.myLayout);
}

Я не думаю, что второй подход работает. Я попробовал; одно действие с EditText. Я написал там какой-то текст, сменил ориентацию, и текст пропал / сбросился.

Ted 09.01.2010 06:20

Надеемся, что в будущем мы увидим метод onRotate (). Честно говоря, необходимость даже беспокоиться о таких вещах расстраивает.

Kelly Sutton 28.07.2010 19:12

Не забывайте keyboardHidden в android:configChanges. Я это сделал, и это все равно привело к уничтожению и воссозданию активности.

beetstra 10.02.2011 03:23

Обратите внимание, что Руководство разработчика Android предостерегает от использования этого: Примечание. Следует избегать использования (android:configChanges) и использовать его только в крайнем случае. Пожалуйста, прочтите «Обработка изменений во время выполнения» для получения дополнительной информации о том, как правильно обрабатывать перезапуск из-за изменения конфигурации. Вместо того, чтобы сохранять данные в событиях вращения, они, кажется, предпочитают использовать onSaveInstanceState Bundle; или как @ Jon-O упоминает, onRetainNonConfigurationInstance.

Jeffro 01.12.2011 23:08

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

Bananeweizen 29.12.2011 12:32

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

bigstones 22.03.2012 01:54

Использование android:configChanges избавляет меня от кучи работы, поэтому я ненавижу, когда Google говорит мне использовать его только в крайнем случае, не объясняя Зачем. Дайте мне повод не экономить кучу работы. Пожалуйста.

Nilzor 01.08.2014 16:08

Google говорит не использовать android:configChanges, потому что: Самостоятельная обработка изменений конфигурации может значительно затруднить использование альтернативных ресурсов, поскольку система не применяет их автоматически.источник Кажется разумным предотвратить портрет / пейзаж с этим, поскольку вы говорите, что не хотите, чтобы он обрабатывался вообще. Предостережение: я android n00b.

Erigami 19.02.2015 04:50

В последнем коде не используйте setContentView. Он будет работать правильно.

Samudra Ganguly 29.07.2020 20:57

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

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

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

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

который имеет дополнительное преимущество в том, что он всегда работает.

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

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

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

Geltrude 12.02.2012 14:51

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

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

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();
}

Чтобы уточнить: с моей реализацией теперь вы можете инициализировать переменную в onCreate (), а onConfigurationChanged () будет просто вызываться для поворота экрана. Ваши переменные теперь изолированы от поворотов экрана ;-) nice and ez

Someone Somewhere 06.04.2011 02:48

Я сделал все, как описано здесь, но получаю исключение NullPointerException, когда пытаюсь нажать кнопку после изменения ориентации. Что могло быть не так?

Finnboy11 21.04.2012 17:47

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

Someone Somewhere 14.11.2013 03:30

В предупреждении против android: configChanges @ SimonAndréForsberg на самом деле просто перефразирует Документы для Android. Обработка изменений среды выполнения содержит более подробную информацию об альтернативах (включая пример кода).

Leif Arne Storset 01.07.2015 15:40

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

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

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

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

Я действительно думаю, что Fragments и setRetainInstance - лучший способ (и рекомендованный Google) для этого, +1 вам и -1 всем остальным. Добавление android: configChanges следует использовать только в крайнем случае

Simon Forsberg 07.11.2013 00:01

В манифест Android необходимо внести следующие изменения:

android:configChanges = "keyboardHidden|orientation" 

Дополнения, которые необходимо сделать внутри деятельности:

public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
        Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
    }
}
 onConfigurationChanged is called when the screen rotates. 
 (onCreate is no longer called when screen rotates due to manifest, see:  
 android:configChanges)

В какой части манифеста сказано «не звонить onCreate()»?

Также, Документы Google говорят, что следует избегать использования android:configChanges (кроме как в крайнем случае) .... Но тогда альтернативные методы, которые они предлагают, все ДЕЛАТЬ используют android:configChanges.

По моему опыту, эмулятор ВСЕГДА вызывает onCreate() при вращении. Но 1-2 устройства, на которых я запускаю один и тот же код ... нет. (Не уверен, почему будет какая-то разница.)

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

Caution: Beginning with Android 3.2 (API level 13), the "screen size" also changes when the device switches between portrait and landscape orientation. Thus, if you want to prevent runtime restarts due to orientation change when developing for API level 13 or higher (as declared by the minSdkVersion and targetSdkVersion attributes), you must include the "screenSize" value in addition to the "orientation" value. That is, you must declare android:configChanges = "orientation|screenSize". However, if your application targets API level 12 or lower, then your activity always handles this configuration change itself (this configuration change does not restart your activity, even when running on an Android 3.2 or higher device).

Спасибо за это разъяснение, поскольку вышеприведенный комментарий чуть не отправил меня изучить это. В настоящее время я нацелен на API 8, и в моем коде нет screenSize в configChanges, и я могу подтвердить, что он работает нормально (без переориентации) на моем устройстве, на котором работает ICS.

Carl 12.03.2012 13:58

Спасибо, что указали на это, у меня был установлен только android: configChanges = "Ориентация | screenSize", и переключение ориентации воссоздавало мою активность, и, хоть убей, я не мог понять, почему!

Christopher Perry 21.07.2012 02:27

Добавление android: configChanges следует использовать только в крайнем случае. Вместо этого рассмотрите возможность использования Fragments и setRetainInstance.

Simon Forsberg 07.11.2013 00:03

Ключевым моментом является screenSize для Android 3.2 и выше, который решил мою проблему. Спасибо!

fantouch 24.01.2016 16:25

Несмотря на то, что это не «способ Android», я получил очень хорошие результаты, обрабатывая изменения ориентации самостоятельно и просто перемещая виджеты в представлении, чтобы учесть измененную ориентацию. Это быстрее, чем любой другой подход, потому что ваши представления не нужно сохранять и восстанавливать. Это также обеспечивает более плавное взаимодействие с пользователем, поскольку измененные виджеты являются точно такими же виджетами, только что перемещенными и / или измененными в размере. Таким образом можно сохранить не только состояние модели, но и состояние просмотра.

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

Я хотел бы увидеть пример кода этого, кажется блестящим!

Henrique de Sousa 18.10.2016 12:23

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

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

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

public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_game_list);

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

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

и где ты на самом деле сохраняешь состояние?

Ewoks 09.08.2012 13:40

это, кажется, работает для меня, и это кажется самым простым методом. Я заметил, что у вас есть только 4 ИБ для этого (5 включая мой) против 373 за идею создания подклассов Application, что мне кажется намного более сложным. Есть ли у этого метода недостатки?

steveh 28.02.2013 06:54

Это решение отлично поработало для меня. Я смог с помощью Intent serverintent = new Intent(MainActivity.this, MessageListener.class); и startService(serverintent); создать serverSocket = new ServerSocket(0xcff2); и Socket client = serverSocket.accept(); с помощью BufferedReader(new InputStreamReader(client.getInputStream())); и мог повернуть свой Android и поддерживать соединение клиент / сервер активным, но при этом повернуть графический интерфейс. Согласно руководству, savedInstanceState инициализируется при завершении последнего действия.

Fred F 28.02.2013 07:27

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

RTF 04.01.2014 05:19

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

LukeWaggoner 02.12.2014 02:32

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

     android:configChanges = "keyboard|keyboardHidden|orientation"

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

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

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

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

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

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

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

Согласовано. С последней версией Android API кажется, что фрагменты - правильный способ справиться с этим. Я сам еще не пробовал, но из того, что я собрал, читая эта страница, вы в основном перемещаете 99% того, что вы использовали для реализации в Activity, в подкласс фрагмента, а затем добавляете этот фрагмент в Activity. Действие по-прежнему будет уничтожено и воссоздано при повороте экрана, но вы можете специально указать Android нет уничтожить фрагмент, используя упомянутый @Abdo метод setRetainInstance().

brianmearns 26.09.2012 23:50

Я нашел способ сделать это - использовать события onRestoreInstanceState и onSaveInstanceState для сохранения чего-либо в Bundle (даже если вам не нужно сохранять какие-либо переменные, просто поместите что-нибудь туда, чтобы Bundle не был пустым). Затем с помощью метода onCreate проверьте, пуст ли Bundle, и если это так, то выполните инициализацию, если нет, то выполните.

Исправить ориентацию экрана (альбомная или портретная) в AndroidManifest.xml

android:screenOrientation = "portrait" или android:screenOrientation = "landscape"

для этого ваш метод onResume() не вызывается.

как, черт возьми, исправить что-то - это ответ? Почему наши устройства могут вращаться, если мы заблокируем их использование пользователями?

Reinherd 15.01.2014 20:56

Поместите этот код ниже в свой Activity в Android Manifest.

android:configChanges = "orientation"

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

@Mavamaarten Вероятно, потому что, как указывали другие, это плохая практика, и десять других ответов уже охватили это.

MikkoP 22.03.2014 22:18

Примечание: Я отправлю этот ответ, если кто-то в будущем столкнется с той же проблемой, что и я. Мне не хватило следующей строчки:

android:configChanges = "orientation"

Когда я повернул экран, метод onConfigurationChanged (Configuration newConfig) не был вызван.

Решение: Мне также пришлось добавить screenSize, даже если проблема была связана с ориентацией. Итак, в файле AndroidManifest.xml добавьте следующее:

android:configChanges = "keyboardHidden|orientation|screenSize"

Затем реализуйте метод onConfigurationChanged(Configuration newConfig)

Вы можете заблокировать текущую ориентацию экрана с помощью этого кода ...

int currentOrientation =context.getResources().getConfiguration().orientation;
        if (currentOrientation == Configuration.ORIENTATION_PORTRAIT) {
            ((Activity) context).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        } else {
            ((Activity) context). setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        }

Добавьте эту строку в свой манифест: -

android:configChanges = "orientation|keyboard|keyboardHidden|screenSize|screenLayout|uiMode"

и этот фрагмент к действию: -

@Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
    }

Поместите приведенный ниже код в тег <activity> в Manifest.xml:

android:configChanges = "screenLayout|screenSize|orientation"

Используйте прослушиватель orientation для выполнения разных задач в разной ориентации.

@Override
public void onConfigurationChanged(Configuration myConfig) 
{
    super.onConfigurationChanged(myConfig);
    int orient = getResources().getConfiguration().orientation; 
    switch(orient) 
    {
       case Configuration.ORIENTATION_LANDSCAPE:
          setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                    break;
       case Configuration.ORIENTATION_PORTRAIT:
          setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                    break;
       default:
          setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
    }
}

После некоторого времени проб и ошибок я нашел решение, которое соответствует моим потребностям в большинстве ситуаций. Вот код:

Конфигурация манифеста:

<?xml version = "1.0" encoding = "utf-8"?>
<manifest xmlns:android = "http://schemas.android.com/apk/res/android"
          package = "com.pepperonas.myapplication">

    <application
        android:name = ".App"
        android:allowBackup = "true"
        android:icon = "@mipmap/ic_launcher"
        android:label = "@string/app_name"
        android:supportsRtl = "true"
        android:theme = "@style/AppTheme">
        <activity
            android:name = ".MainActivity"
            android:configChanges = "orientation|keyboardHidden|screenSize">
            <intent-filter>
                <action android:name = "android.intent.action.MAIN"/>

                <category android:name = "android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>

</manifest>

Основная деятельность:

import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String TAG = "MainActivity";

    private Fragment mFragment;

    private int mSelected = -1;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate  " + "");

        // null check not realy needed - but just in case...
        if (savedInstanceState == null) {

            initUi();

            // get an instance of FragmentTransaction from your Activity
            FragmentManager fragmentManager = getSupportFragmentManager();
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

            /*IMPORTANT: Do the INITIAL(!) transaction only once!
            * If we call this everytime the layout changes orientation,
            * we will end with a messy, half-working UI.
            * */
            mFragment = FragmentOne.newInstance(mSelected = 0);
            fragmentTransaction.add(R.id.frame, mFragment);
            fragmentTransaction.commit();
        }
    }


    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        Log.d(TAG, "onConfigurationChanged  " +
                   (newConfig.orientation
                    == Configuration.ORIENTATION_LANDSCAPE
                    ? "landscape" : "portrait"));

        initUi();

        Log.i(TAG, "onConfigurationChanged - last selected: " + mSelected);
        makeFragmentTransaction(mSelected);
    }


    /**
     * Called from {@link #onCreate} and {@link #onConfigurationChanged}
     */
    private void initUi() {
        setContentView(R.layout.activity_main);
        Log.d(TAG, "onCreate  instanceState == null / reinitializing..." + "");
        Button btnFragmentOne = (Button) findViewById(R.id.btn_fragment_one);
        Button btnFragmentTwo = (Button) findViewById(R.id.btn_fragment_two);
        btnFragmentOne.setOnClickListener(this);
        btnFragmentTwo.setOnClickListener(this);
    }


    /**
     * Not invoked (just for testing)...
     */
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        Log.d(TAG, "onSaveInstanceState  " + "YOU WON'T SEE ME!!!");
    }


    /**
     * Not invoked (just for testing)...
     */
    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        Log.d(TAG, "onSaveInstanceState  " + "YOU WON'T SEE ME, AS WELL!!!");
    }


    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "onResume  " + "");
    }


    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "onPause  " + "");
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy  " + "");
    }


    @Override
    public void onClick(View v) {

        switch (v.getId()) {
            case R.id.btn_fragment_one:
                Log.d(TAG, "onClick btn_fragment_one " + "");
                makeFragmentTransaction(0);
                break;

            case R.id.btn_fragment_two:
                Log.d(TAG, "onClick btn_fragment_two " + "");
                makeFragmentTransaction(1);
                break;

            default:
                Log.d(TAG, "onClick  null - wtf?!" + "");
        }
    }


    /**
     * We replace the current Fragment with the selected one.
     * Note: It's called from {@link #onConfigurationChanged} as well.
     */
    private void makeFragmentTransaction(int selection) {

        switch (selection) {
            case 0:
                mFragment = FragmentOne.newInstance(mSelected = 0);
                break;
            case 1:
                mFragment = FragmentTwo.newInstance(mSelected = 1);
                break;
        }

        // Create new transaction
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

        // Replace whatever is in the fragment_container view with this fragment,
        // and add the transaction to the back stack
        transaction.replace(R.id.frame, mFragment);

        /*This would add the Fragment to the backstack...
        * But right now we comment it out.*/
        //        transaction.addToBackStack(null);

        // Commit the transaction
        transaction.commit();
    }

}

И образец фрагмента:

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * @author Martin Pfeffer (pepperonas)
 */
public class FragmentOne extends Fragment {

    private static final String TAG = "FragmentOne";


    public static Fragment newInstance(int i) {
        Fragment fragment = new FragmentOne();
        Bundle args = new Bundle();
        args.putInt("the_id", i);
        fragment.setArguments(args);
        return fragment;
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Log.d(TAG, "onCreateView  " + "");
        return inflater.inflate(R.layout.fragment_one, container, false);
    }

}

Можно найти на github.

Это очень просто, достаточно проделать следующие шаги:

<activity
    android:name = ".Test"
    android:configChanges = "orientation|screenSize"
    android:screenOrientation = "landscape" >
</activity>

Это работает для меня:

Ориентация Примечание: зависит от ваших требований

Есть несколько способов сделать это:

Сохранить состояние активности

Вы можете сохранить состояние активности в onSaveInstanceState.

@Override
public void onSaveInstanceState(Bundle outState) {
    /*Save your data to be restored here
    Example : outState.putLong("time_state", time); , time is a long variable*/
    super.onSaveInstanceState(outState);
}

а затем используйте bundle для восстановления состояния.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if (savedInstanceState!= null){
       /*When rotation occurs
        Example : time = savedInstanceState.getLong("time_state", 0); */
    } else {
      //When onCreate is called for the first time
    }
}

Самостоятельно справляться с изменением ориентации

Другой вариант - самостоятельно справиться с изменением ориентации. Но это не считается хорошей практикой.

Добавьте это в свой файл манифеста.

android:configChanges = "keyboardHidden|orientation"

для Android 3.2 и новее:

android:configChanges = "keyboardHidden|orientation|screenSize"

@Override
public void onConfigurationChanged(Configuration config) {
    super.onConfigurationChanged(config);

if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
        //Handle rotation from landscape to portarit mode here
    } else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE){
        //Handle rotation from portrait to landscape mode here
    }
}

Ограничить вращение

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

Добавьте это в тег активности в файле манифеста:

        android:screenOrientation = "portrait"

Или реализуйте это программно в своей деятельности:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}

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

@Override
    public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
        super.onSaveInstanceState(outState, outPersistentState);
        outPersistentState.putBoolean("key",value);
    }

и использовать

@Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        savedInstanceState.getBoolean("key");
    } 

получить и установить значение для просмотра объектов он будет обрабатывать поворот экрана

Каждый раз, когда экран поворачивается, открытое действие завершается и onCreate () вызывается снова.

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

2. Если вы хотите предотвратить перезапуск активности, просто поместите следующие строки в свой файл manifest.xml.

  <activity android:name = ".Youractivity"
  android:configChanges = "orientation|screenSize"/>

В разделе активности manifest добавьте:

android:configChanges = "keyboardHidden|orientation"

Добавьте эту строку в манифест:android:configChanges = "orientation|screenSize"

Люди говорят, что вам следует использовать

android:configChanges = "keyboardHidden|orientation"

Но лучший и самый профессиональный способ управлять вращением в Android - использовать класс Loader. Это не известный класс (я не знаю почему), но он намного лучше, чем AsyncTask. Для получения дополнительной информации вы можете прочитать учебные материалы по Android, которые можно найти в курсах Udacity для Android.

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

Да, давайте добавим кучу дополнительного кода, чтобы он выглядел «профессионально». Или как насчет того, чтобы просто придерживаться быстрого, простого, надежного и испытанного способа сделать это с атрибутом configurationChanges.

AndroidDev 19.05.2019 10:55

Вы можете использовать объект ViewModel в своей деятельности.

Объекты ViewModel автоматически сохраняются во время изменения конфигурации, поэтому данные, которые они хранят, немедленно становятся доступными для следующего действия или экземпляра фрагмента. Читать далее:

https://developer.android.com/topic/libraries/architecture/viewmodel

Один из лучших компонентов архитектуры Android, представленный Google, выполнит все ваши требования, а именно ViewModel.

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

class MyViewModel : ViewModel() {

Пожалуйста, обратитесь к этому: https://developer.android.com/topic/libraries/architecture/viewmodel

Есть несколько способов сделать это:

Самостоятельно справляться с изменением ориентации

Другой вариант - самостоятельно справиться с изменением ориентации. Но это не считается хорошей практикой.

Добавьте это в свой файл манифеста.

android:configChanges = "keyboardHidden|orientation"

для Android 3.2 и новее:

android:configChanges = "keyboardHidden|orientation|screenSize"

@Override
public void onConfigurationChanged(Configuration config) {
    super.onConfigurationChanged(config);

if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
        //Handle rotation from landscape to portarit mode here
    } else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE){
        //Handle rotation from portrait to landscape mode here
    }
}

ИЛИ Ограничить вращение

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

Добавьте это в тег активности в файле манифеста:

android: screenOrientation = "портрет"

Или реализуйте это программно в своей деятельности:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}

ИЛИ Сохранить состояние активности

Вы можете сохранить состояние активности в onSaveInstanceState.

@Override
public void onSaveInstanceState(Bundle outState) {
    /*Save your data to be restored here
    Example : outState.putLong("time_state", time); , time is a long variable*/
    super.onSaveInstanceState(outState);
}

а затем используйте пакет для восстановления состояния.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if (savedInstanceState!= null){
       /*When rotation occurs
        Example : time = savedInstanceState.getLong("time_state", 0); */
    } else {
      //When onCreate is called for the first time
    }
}

добавьте этот код в свой menufests.xml.

это ваша деятельность.

<activity
....
..
android:configChanges = "orientation|screenSize"/>

Другие вопросы по теме