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

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

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

Ответы [ 31 ]

6 голосов
/ 07 декабря 2016

вам нужно использовать метод 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");
    } 

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

5 голосов
/ 10 марта 2017

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

android:configChanges="keyboardHidden|orientation"
5 голосов
/ 28 ноября 2017

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

4 голосов
/ 09 января 2018

Люди говорят, что вы должны использовать

android:configChanges="keyboardHidden|orientation"

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

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

3 голосов
/ 15 февраля 2013

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

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

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

3 голосов
/ 30 октября 2015

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

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

<?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 голосов
/ 04 февраля 2015

Используйте 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 голосов
/ 29 июля 2013

Введите этот код ниже в Activity в Android Manifest.

android:configChanges="orientation"

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

2 голосов
/ 24 октября 2018

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

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

class MyViewModel : ViewModel() {

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

0 голосов
/ 19 сентября 2018

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

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

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

...