Перезапуск активності на обертовому Android


1379

У моєму додатку Android, коли я обертаю пристрій (висуваю клавіатуру), тоді мій Activityперезапускається ( onCreateназивається). Зараз, мабуть, так і має бути, але я роблю багато початкових налаштувань onCreateметоду, тому мені потрібно:

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

4
Існує досить повне пояснення, як зберегти тривалі асинхронні завдання під час зміни конфігурації діяльності і в цьому дописі блогу !
Адріан Чернець

3
Це не пряма відповідь, як вже відповіли інші, але я пропоную вам ознайомитись з LogLifeCycle, щоб зрозуміти, що відбувається у ваших додатках для Android щодо життєвих циклів.
Snicolas

Відповіді:


965

Використання класу додатків

Залежно від того, що ви робите під час ініціалізації, ви можете розглянути можливість створення нового класу, який розширює Applicationі переміщує код ініціалізації в переосмислений onCreateметод у цьому класі.

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

Клас onCreateдодатка викликається лише тоді, коли створено всю програму, тому активність перезапуститься при орієнтації або зміни видимості клавіатури не запустить її.

Добре розкривати екземпляр цього класу як сингл та викрити змінні програми, які ви ініціалізуєте, використовуючи getters та setters.

ПРИМІТКА. Вам потрібно буде вказати ім'я вашого нового класу додатків у маніфесті для його реєстрації та використання:

<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">

Тоді в межах Діяльності замініть onConfigurationChangedметод і заклик setContentViewзмусити повторно виконати макет GUI у новій орієнтації.

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

17
Я не думаю, що другий підхід працює. Я спробував це; одна активність з EditText. Я написав там якийсь текст, змінив орієнтацію і текст пішов / скинувся.
Тед

231
Ось сподіваємось, що в майбутньому ми побачимо метод onRotate (). Навіть турбуватися про такі речі - відверто кажучи, неприємно.
Келлі Саттон

84
Зауважте, що посібник Android Dev застерігає від використання цього: Примітка. Використання ( android:configChanges) слід уникати та використовувати лише в крайньому випадку. Будь ласка, прочитайте Поводження із змінами часу виконання для отримання додаткової інформації про те, як правильно впоратися з перезапуском через зміну конфігурації. Замість цього, щоб зберігати дані по поворотах, вони, здається, вважають за краще використовувати onSaveInstanceState Bundle; або як @ Jon-O згадує , onRetainNonConfigurationInstance.
Jeffro

19
Це неправильне рішення, оскільки воно реагує лише на відомі на сьогодні зміни конфігурації. З новішими версіями Android можуть відбуватися інші зміни конфігурації, які цей код не буде вловлювати (оскільки він повинен перераховувати всі зміни конфігурації в маніфесті). Рішення врятувати стан з onRetainNonConfigurationChangesбільш віростійким і прямим вперед.
Bananeweizen

16
Я думаю, ви повинні додати це оновлення на 3.2 до своєї відповіді, це дуже важливо (щойно зіткнувся з цією проблемою) і воно може не помітити.
bigstones

185

Оновлення для Android 3.2 та новіших версій:

Попередження : Починаючи з Android 3.2 (API рівня 13), "розмір екрана" також змінюється, коли пристрій перемикається між портретною та пейзажною орієнтацією. Таким чином, якщо ви хочете запобігти перезапуску виконуваного часу через зміну орієнтації при розробці для API рівня 13 або вище (як заявлено атрибутами minSdkVersion та targetSdkVersion), вам слід додати "screenSize"значення додатково до "orientation"значення. Тобто ви повинні заявити android:configChanges="orientation|screenSize". Однак якщо ваша програма орієнтована на рівень API 12 або нижчий, ваша активність завжди обробляє цю зміну конфігурації (ця зміна конфігурації не перезапускає вашу активність навіть під час роботи на пристрої Android 3.2 або новішої версії).


1
Дякую за це роз’яснення, оскільки коментар, поданий вище з цього приводу, майже відправив мене на розгляд. В даний час я націлююсь на API 8, і мій код не має розміру екрана на configChanges і можу підтвердити, що він добре працює (без переорієнтації) на пристрої, на якому працює ICS.
Карл

Дякую, що вказав на це, у мене був лише android: configChanges = "орієнтація | screenSize", а переключення орієнтації відтворювало мою активність, і я не міг зрозуміти чому!
Крістофер Перрі

5
Додавання android: configChanges слід використовувати лише в крайньому випадку . Подумайте про використання Fragmentsта setRetainInstanceзамість цього.
Саймон Форсберг

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

127

Замість того, щоб намагатися onCreate()взагалі не зупиняти звільнення, можливо, спробуйте перевірити, Bundle savedInstanceStateчи передається він у події, щоб переконатися, що воно є нульовим чи ні.

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

В іншому випадку я все ще хочу, щоб макет переробив належним чином для орієнтації.

public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_game_list);

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

не впевнений, чи це остаточна відповідь, але це працює на мене.


6
і де ти насправді економія держави?
Евокс

5
це, здається, працює для мене, і, здається, це найпростіший метод. Я зауважую, що у вас було лише 4 підходи (5, включаючи мою) проти 373 за ідею про додаток для підкласингу, що мені здається набагато складнішим. Чи є якийсь мінус у цього методу?
steveh

4
Це рішення спрацювало ВЕЛИКО для мене. я був в стані Intent serverintent = new Intent(MainActivity.this, MessageListener.class);і startService(serverintent);створити serverSocket = new ServerSocket(0xcff2);і Socket client = serverSocket.accept();з BufferedReader(new InputStreamReader(client.getInputStream()));і можу повернути мій андроїд і підтримувати зв'язок з клієнтами / сервера активні, але має графічний інтерфейс обертатися. Згідно з посібником, збережений файлInstanceState ініціалізується, коли остання активність відключена.
Фред Ф

3
Я не розумію, у чому ловить? Це працює чудово і з значно меншою складністю, ніж будь-яке інше рішення.
RTF

3
Це правильний спосіб зробити це в Android. Інші способи зафіксувати обертовий за допомогою configChanges та всі об'ємні, складні та непотрібні.
LukeWaggoner

99

що я зробив...

у маніфесті до розділу про діяльність додано:

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

3
щоб уточнити: з моєю реалізацією тепер ви можете мати ініціалізацію змінної в onCreate (), а onConfigurationChanged () буде просто викликано для обертання екрана. Ваші змінні тепер захищені від обертання екрана ;-) nice and ez
Хтось десь

2
Я все робив так, як описано тут, але отримую NullPointerException, коли намагаюся натиснути кнопку після зміни орієнтації. Що може бути не так?
Finnboy11

5
майте на увазі, моя відповідь - це 3 роки, а Android постійно розвивається ... Саймон - у вас є посилання на зразок коду? Це те, що потрібно людям.
Хтось десь

3
Під час попередження проти android: configChanges, @ SimonAndréForsberg насправді просто перефразовує документи Android . Поводження зі змінами часу виконання містить більш детальну інформацію про альтернативи (включаючи зразок коду).
Лейф Арн Шторсет

67

Те, що ви описуєте, - це поведінка за замовчуванням. Ви повинні виявити та обробити ці події самостійно, додавши:

android:configChanges

на ваш маніфест, а потім на зміни, які ви хочете вжити. Отже, для орієнтації ви б використовували:

android:configChanges="orientation"

а для відкриття чи закриття клавіатури ви використовуєте:

android:configChanges="keyboardHidden"

Якщо ви хочете обробити обидва, ви можете просто розділити їх командою pipe на зразок:

android:configChanges="keyboardHidden|orientation"

Це запустить метод onConfigurationChanged у будь-якій діяльності, яку ви викликаєте. Якщо ви перекриєте метод, ви можете передати нові значення.

Сподіваюсь, це допомагає.


2
@GregD Я знаю, саме тому зараз найкращий час оновити його, щоб відобразити ситуацію сьогодні. Зважаючи на кількість обґрунтованих результатів цього питання, воно все ще посилається на інші запитання щодо ПЗ.
Саймон Форсберг

48

Я щойно виявив цю красу:

Щоб зберегти активність за допомогою зміни орієнтації та обробляти її onConfigurationChanged, документація та зразок коду вище пропонують це у файлі Manifest:

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

що має додаткову користь від того, що вона завжди працює.

Бонусна доля полягає в тому, що опущення зображення keyboardHiddenможе здатися логічним, але воно спричиняє збої в емуляторі (як мінімум для Android 2.1): якщо вказати лише orientation, емулятор буде викликати OnCreateі onConfigurationChangedінколи, і лише OnCreateінший час.

Я не бачив несправності на пристрої, але чув про те, як емулятор вийшов з ладу для інших. Тож варто документувати.


14
Попередження: Починаючи з Android 3.2 (API рівня 13), "розмір екрана" також змінюється, коли пристрій перемикається між портретною та пейзажною орієнтацією. Таким чином, якщо ви хочете запобігти перезапуску часу виконання через зміни орієнтації при розробці для API рівня 13 або вище: android: configChanges = "орієнтація | клавіатураHidden | screenSize"
Geltrude

Так, емулятор смокче великий час. Ви не можете покластися на нього, щоб точно повідомити про зміни конфігурації.
ІгорГанапольський

Додавання android: configChanges слід використовувати лише в крайньому випадку . Подумайте про використання Fragmentsта setRetainInstanceзамість цього.
Саймон Форсберг

38

Ви також можете скористатися способом збереження даних платформи Android через зміни орієнтації: onRetainNonConfigurationInstance()і getLastNonConfigurationInstance().

Це дозволяє зберігати дані через зміни конфігурації, наприклад, інформацію, яку ви отримали від завантаження сервера або щось інше, що було обчислено в onCreateабо після цього, а також дозволить Android перепланувати ваш Activityфайл, використовуючи файл xml для орієнтації, який зараз використовується .

Дивіться тут або тут .

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


3
Я дійсно думаю, що фрагменти та setRetainInstance - це найкращий спосіб (і рекомендований Google), щоб зробити це, +1 вам і -1 для всіх інших. Додавання android: configChanges слід використовувати лише в крайньому випадку
Simon Forsberg

32

Підхід корисний, але неповний при використанні фрагментів.

Фрагменти зазвичай відтворюються при зміні конфігурації. Якщо ви не хочете, щоб це сталося, використовуйте

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

Це призведе до збереження фрагментів під час зміни конфігурації.

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


7
Домовились. З найновішим Android API, здається, фрагменти є правильним способом впоратися з цим. Я ще не пробував цього ще, але з того, що я зібрав, читаючи цю сторінку , ви в основному переміщаєте 99% того, що використовували для реалізації в діяльності, в підклас фрагмента, а потім додаєте цей фрагмент до діяльності. Діяльність все одно буде знищена та відтворена під час обертання екрана, але ви можете конкретно сказати андроїду не руйнувати фрагмент, використовуючи setRetainInstance()згаданий метод @Abdo.
brianmearns

25

Я просто додав

     android:configChanges="keyboard|keyboardHidden|orientation"

у файл маніфесту та не додав жодного onConfigurationChangedметоду у свою діяльність.

Тому кожен раз, коли клавіатура вислизає або нічого не відбувається .


додано до <application ...android:configChanges="keyboard|keyboardHidden|orientation">і воно працює. Мої налаштування в build.gradle:minSdkVersion 15, compileSdkVersion 23, buildToolsVersion "23.0.2"
Junior Mayhé

19

Цей onCreateметод все ще називається, навіть якщо ви змінюєте orientationандроїд. Тому перенесення всіх важких функціональних можливостей на цей метод вам не допоможе



17
 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(крім крайнього випадку) .... Але тоді альтернативні методи, які вони пропонують використовувати всі DOandroid:configChanges .

Як мій досвід, емулятор ЗАВЖДИ викликає onCreate()обертання.
Але 1-2 пристрої, на яких я запускаю той самий код, ... ні. (Не впевнений, чому була б якась різниця.)


16

Дуже просто виконати наступні дії:

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

Це працює для мене:

Примітка: орієнтація залежить від вашої вимоги


15

Зміни, які слід внести в маніфест 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();
    }
}

15

Додайте цей рядок до свого маніфесту: -

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

14

Існує кілька способів зробити це:

Зберегти стан активності

Ви можете зберегти стан активності в 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);
}

11

Я знайшов це зробити, використовуючи onRestoreInstanceStateі onSaveInstanceStateподії, щоб щось зберегти в Bundle(навіть якщо вам не потрібні збережені змінні, просто покладіть щось там, щоб Bundleвоно не було порожнім). Потім у onCreateметоді перевірте, чи Bundleє порожнім, а якщо він є, то зробіть ініціалізацію, якщо ні, то зробіть це.


11

Незважаючи на те, що це не "Android-спосіб", я отримав дуже хороші результати, обробляючи зміни орієнтації і просто переміщуючи віджети в межах перегляду, щоб врахувати змінену орієнтацію. Це швидше, ніж будь-який інший підхід, тому що ваші погляди не потрібно зберігати та відновлювати. Він також забезпечує більш легкий досвід користувачеві, тому що відредаговані віджети - це саме ті самі віджети, щойно переміщені та / або змінені. Таким чином можна зберегти не тільки стан моделі, але і стан перегляду.

RelativeLayoutІноді може бути хорошим вибором для погляду, який час від часу повинен переорієнтуватися. Ви просто надаєте набір портретних макетів параметри та набір параметри ландшафтного компонування з різними правилами відносного розміщення на кожному для кожного довідкового віджета. Потім у вашому onConfigurationChanged()методі ви передаєте відповідний setLayoutParams()дзвінок кожній дитині. Якщо будь-який контроль над дитиною сам по собі потребує внутрішньої переорієнтації, ви просто зателефонуєте на цю методику, щоб виконати переорієнтацію. Ця дитина аналогічно називає методи будь-якого зі своїх дочірніх засобів управління, які потребують внутрішньої переорієнтації тощо.


Я хотів би побачити якийсь зразок коду цього, здається геніальним!
Анріке де Соуза

8

Кожен раз, коли екран обертається, відкрита діяльність закінчується, і onCreate () викликається знову.

1. Ви можете зробити одне, щоб зберегти стан активності, коли екран повернути так, що Ви можете відновити всі старі речі, коли onCreate () викликається знову. Перейдіть за цим посиланням

2. Якщо ви хочете запобігти перезапуску активності, просто розмістіть у файлі manifest.xml наступні рядки.

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

7

вам потрібно використовувати метод 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");
    } 

щоб відновити та встановити значення для перегляду об'єктів, воно обробляє обертання екрана


Для цього потрібен рівень 22.
Мохаммед Афраштех

6

Примітка: я публікую цю відповідь, якщо хтось у майбутньому зіткнеться з тією ж проблемою, що і я. Для мене наступний рядок не був зрозумілий:

android:configChanges="orientation"

Коли я повернув екран, метод `onConfigurationChanged (Configuration newConfig) не викликався.

Рішення: мені також довелося додати "screenSize", навіть якщо проблема пов'язана з орієнтацією. Тож у AndroidManifest.xml - файл, додайте це:

android:configChanges="keyboardHidden|orientation|screenSize"

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




4

Люди кажуть, що вам слід користуватися

android:configChanges="keyboardHidden|orientation"

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

Звичайно, як інший спосіб, ви можете зберігати значення або представлення з допомогою OnSaveInstanceState і читати їх за допомогою onRestoreInstanceState. Це справді залежить від вас.


Так, давайте додамо гебі з додатковим кодом, щоб виглядати "професійно". А як щодо просто дотримуватися швидкий, простий, правдивий і перевірений спосіб зробити це за допомогою атрибута configChanges.
AndroidDev

3

Через деякий час спроб та помилок я знайшов рішення, яке відповідає моїм потребам у більшості ситуацій. Ось код:

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

<?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>

MainActivity:

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 .


3

Використовуйте 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);
    }
}

3

Помістіть це нижче коду в Activityін Android Manifest.

android:configChanges="orientation"

Це не перезапустить вашу діяльність, коли ви зміните орієнтацію.


2
@Mavamaarten Напевно, тому, що, як зазначали інші, це погана гра, і десять інших відповідей вже висвітлювали це.
MikkoP

3

Зафіксуйте орієнтацію екрана (пейзаж або портрет) в AndroidManifest.xml

android:screenOrientation="portrait" або android:screenOrientation="landscape"

для цього ваш onResume()метод не називається.


5
як чорт, що щось виправляє, є відповіддю? Чому наші пристрої можуть обертатися, якщо ми блокуємо користувачів, які користуються ним?
Райнгерд

3

Один з найкращих компонентів Android-архітектури, представлений google, виконає всі ваші вимоги, які має ViewModel.

Це призначено для зберігання та управління даними, пов’язаними з інтерфейсом користувача, у життєвому циклі, а також дозволить зберегти дані під час обертання екрана

class MyViewModel : ViewModel() {

Будь ласка, зверніться до цього: https://developer.android.com/topic/libraries/architecture/viewmodel


1

Ви можете використовувати об’єкт ViewModel у своїй діяльності.

Об'єкти ViewModel автоматично зберігаються під час зміни конфігурації, щоб дані, які вони зберігають, були негайно доступними для наступного екземпляра активності або фрагмента. Детальніше:

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.