Reinício da atividade na rotação Android

1380

No meu aplicativo Android, quando eu giro o dispositivo (deslize o teclado para fora), o meu Activityé reiniciado ( onCreateé chamado). Agora, provavelmente é assim que deve ser, mas eu faço muita configuração inicial no onCreatemétodo, então preciso:

  1. Coloque toda a configuração inicial em outra função para que nem tudo seja perdido na rotação do dispositivo ou
  2. Faça assim onCreate não seja chamado novamente e o layout apenas se ajuste ou
  3. Limite o aplicativo apenas a retrato para que onCreatenão seja chamado.
Isaac Waller
fonte
4
Há uma explicação bastante completa sobre como reter tarefas assíncronas de execução demorada durante as alterações na configuração da atividade também nesta postagem do blog !
Adrian Monk
3
Esta não é uma resposta direta, já que outras pessoas já responderam, mas convido você a dar uma olhada no LogLifeCycle para entender o que acontece em seus aplicativos Android em relação aos ciclos de vida.
Snicolas

Respostas:

965

Usando a classe de aplicativo

Dependendo do que você está fazendo em sua inicialização, você pode considerar criar uma nova classe que estenda Applicatione mova seu código de inicialização para um onCreatemétodo substituído dentro dessa classe.

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

o onCreate classe na aplicação é chamada somente quando o aplicativo inteiro é criado; portanto, a atividade é reiniciada com alterações na orientação ou na visibilidade do teclado não a acionará.

É uma boa prática expor a instância desta classe como um singleton e expor as variáveis ​​de aplicativo que você está inicializando usando getters e setters.

NOTA: Você precisará especificar o nome da sua nova classe Application no manifesto para que ela seja registrada e usada:

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

Reagindo a alterações na configuração [UPDATE: isso foi preterido desde a API 13; veja a alternativa recomendada ]

Como alternativa adicional, você pode fazer com que seu aplicativo escute eventos que causariam uma reinicialização - como alterações na orientação e na visibilidade do teclado - e lide com eles na sua Atividade.

Comece adicionando o android:configChangesnó ao nó de manifesto da sua atividade

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

ou para Android 3.2 (API nível 13) e mais recente :

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

Em seguida, na Atividade, substitua o onConfigurationChangedmétodo e chame setContentViewpara forçar o layout da GUI a ser refazer na nova orientação.

@Override
public void onConfigurationChanged(Configuration newConfig) {
  super.onConfigurationChanged(newConfig);
  setContentView(R.layout.myLayout);
}
Reto Meier
fonte
17
Não acho que a segunda abordagem funcione. Eu tentei; uma atividade com um EditText. Escrevi algum texto lá, mude a orientação e o texto foi apagado / redefinido.
Ted
231
Esperamos ver um método onRotate () no futuro. Ter que se preocupar com coisas assim é - francamente - frustrante.
Kelly Sutton
84
Observe que o Android Dev Guide recomenda não usar isso: Nota: O uso de ( android:configChanges) deve ser evitado e usado apenas como último recurso. Leia Manipulando alterações no tempo de execução para obter mais informações sobre como lidar adequadamente com uma reinicialização devido a uma alteração na configuração. Em vez disso, para persistir os dados nos eventos de rotação, eles parecem preferir usar o onSaveInstanceState Bundle; ou como @ Jon-O menciona , onRetainNonConfigurationInstance.
Jeffro
19
Essa é uma solução ruim, porque reage apenas às alterações de configuração atualmente conhecidas . Nas versões mais recentes do Android, podem ocorrer outras alterações na configuração que este código não capturará (porque deve listar todas as alterações na configuração no manifesto). A solução de salvar o estado onRetainNonConfigurationChangesé mais tolerante a falhas e direta.
Bananeweizen
16
Eu acho que você deve adicionar esta atualização no 3.2 à sua resposta, é muito importante (acabou de enfrentar esse problema) e pode ser ignorada.
bigstones 21/03
185

Atualização para o Android 3.2 e superior:

Cuidado : a partir do Android 3.2 (nível 13 da API), o "tamanho da tela" também muda quando o dispositivo alterna entre a orientação retrato e paisagem. Portanto, se você deseja impedir a reinicialização do tempo de execução devido a alterações de orientação ao desenvolver para o nível 13 da API ou superior (conforme declarado pelos atributos minSdkVersion e targetSdkVersion), inclua o "screenSize"valor além do "orientation"valor. Ou seja, você deve declarar android:configChanges="orientation|screenSize". No entanto, se seu aplicativo atingir o nível 12 ou inferior da API, sua atividade sempre lida com essa alteração de configuração (ela não reinicia sua atividade, mesmo quando executada em um dispositivo Android 3.2 ou superior).

Gorm
fonte
1
Obrigado por esse esclarecimento, uma vez que um comentário acima sobre isso quase me levou a investigar. Atualmente, estou direcionando a API 8 e meu código não tem screenSize em configChanges e posso confirmar que ele funciona bem (sem reorientar) no dispositivo que tenho que está executando o ICS.
1212 Carl
Obrigado por apontar isso, eu tinha apenas o android: configChanges = "guidance | screenSize" configurado, e a troca de orientação estava recriando minha atividade, e durante toda a minha vida eu não conseguia descobrir o porquê!
21412 Christopher Christopher
5
Adicionar android: configChanges deve ser usado apenas como último recurso . Considere usar Fragmentse em setRetainInstancevez disso.
Simon Forsberg
O ponto chave é screenSizepara o Android 3.2 e superior, que resolveu o meu problema, obrigado!
precisa saber é
127

Em vez de tentar impedir que o onCreate()disparador seja totalmente disparado, talvez tente verificar o que Bundle savedInstanceStatefoi passado no evento para ver se é nulo ou não.

Por exemplo, se eu tiver alguma lógica que deva ser executada quando a Activitycriação for realmente criada, e não em todas as mudanças de orientação, eu só executarei essa lógica onCreate()somente se savedInstanceStatefor nula.

Caso contrário, ainda quero que o layout seja redesenhado corretamente para a orientação.

public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_game_list);

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

não tenho certeza se essa é a resposta definitiva, mas funciona para mim.

nebulosas
fonte
6
e onde você está realmente salvando o estado?
Ewoks
5
isso parece funcionar para mim e parece de longe o método mais simples. Percebo que você só tem 4 ups para isso (5 incluindo o meu) vs. 373 para a idéia de subclassificar Application, o que para mim parece muito mais complicado. existe alguma desvantagem nesse método?
28513 steveh
4
Esta solução funcionou muito bem para mim. eu era capaz de Intent serverintent = new Intent(MainActivity.this, MessageListener.class);e startService(serverintent);para criar um serverSocket = new ServerSocket(0xcff2);e Socket client = serverSocket.accept();com um BufferedReader(new InputStreamReader(client.getInputStream()));e poderia girar minha android e manter a conexão cliente / servidor ativo, ainda têm a rotação GUI. De acordo com o manual, savedInstanceState é inicializado quando a última atividade é encerrada.
Fred F
3
Eu não entendo, qual é o problema? Isso funciona muito bem e com muito menos complexidade do que qualquer outra solução.
RTF
3
Esta é a maneira correta de fazer isso no Android. As outras maneiras de basicamente capturar uma rotação com o configChanges e tudo o que é volumoso, complexo e desnecessário.
precisa saber é o seguinte
99

o que eu fiz...

no manifesto, na seção de atividades, adicionou:

android:configChanges="keyboardHidden|orientation"

no código da atividade, implementado:

//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();
}
Alguém algum lugar
fonte
3
para esclarecer: com minha implementação, agora você pode ter a inicialização variável em onCreate () e onConfigurationChanged () será simplesmente chamada para a rotação da tela. Suas variáveis agora são isolados a partir de rotações de tela ;-) agradável e ez
alguém em algum lugar
2
Fiz tudo conforme descrito aqui, mas recebo NullPointerException quando tento pressionar um botão após a alteração da orientação. O que pode estar errado?
precisa saber é o seguinte
5
tenha em mente que minha resposta é como 3 anos e o Android continua evoluindo ... Simon - você tem um link para exemplo de código? É disso que as pessoas precisam.
Alguém em algum lugar
3
Ao alertar contra android: configChanges, o @ SimonAndréForsberg está apenas parafraseando os documentos do Android . O tratamento de alterações no tempo de execução possui informações mais detalhadas sobre as alternativas (incluindo código de exemplo).
Leif Arne Storset
67

O que você descreve é ​​o comportamento padrão. Você precisa detectar e manipular esses eventos você mesmo adicionando:

android:configChanges

ao seu manifesto e, em seguida, às alterações que você deseja manipular. Portanto, para orientação, você usaria:

android:configChanges="orientation"

e para o teclado ser aberto ou fechado, você usaria:

android:configChanges="keyboardHidden"

Se você quiser lidar com ambos, basta separá-los com o comando pipe, como:

android:configChanges="keyboardHidden|orientation"

Isso acionará o método onConfigurationChanged em qualquer atividade que você chamar. Se você substituir o método, poderá passar os novos valores.

Espero que isto ajude.

GregD
fonte
2
@ GregD eu sei, e é por isso que agora é um bom momento para atualizá-lo para refletir a situação de hoje. Dado o número de votos positivos que essa pergunta possui, ela ainda está sendo referida em outras questões sobre SO.
Simon Forsberg
48

Acabei de descobrir esta sabedoria:

Para manter a Atividade viva por meio de uma mudança de orientação e manipulá-la onConfigurationChanged, a documentação e o exemplo de código acima sugerem isso no arquivo Manifest:

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

que tem o benefício extra de sempre funcionar.

O lore bônus é que omitindo o keyboardHiddenpode parecer lógico, mas provoca falhas no emulador (para Android 2.1 pelo menos): especificando única orientationvai fazer a chamada emulador de ambos OnCreatee onConfigurationChanged, por vezes, e apenas OnCreateoutras vezes.

Não vi a falha em um dispositivo, mas ouvi falar que o emulador falhou para outras pessoas. Então vale a pena documentar.

Liudvikas Bukys
fonte
14
Cuidado: a partir do Android 3.2 (API nível 13), o "tamanho da tela" também muda quando o dispositivo alterna entre a orientação retrato e paisagem. Portanto, se você deseja impedir a reinicialização do tempo de execução devido a alterações de orientação ao desenvolver para o nível 13 da API: android: configChanges = "guidance | keyboardHidden | screenSize"
Geltrude
Sim, o emulador é péssimo. Você não pode confiar nele para relatar alterações de configuração com precisão.
IgorGanapolsky
Adicionar android: configChanges deve ser usado apenas como último recurso . Considere usar Fragmentse em setRetainInstancevez disso.
Simon Forsberg
38

Você também pode considerar usar o modo de persistência de dados da plataforma Android através de alterações de orientação: onRetainNonConfigurationInstance()e getLastNonConfigurationInstance().

Isso permite que você persista os dados nas alterações de configuração, como informações que você pode ter obtido de uma busca no servidor ou qualquer outra coisa que tenha sido computada onCreateou desde então, além de permitir que o Android redimensione seu Activityuso do arquivo xml para a orientação agora em uso .

Veja aqui ou aqui .

Deve-se notar que esses métodos agora estão obsoletos (embora ainda mais flexíveis do que a orientação de manipulação, mude a si mesmo, como sugere a maioria das soluções acima), com a recomendação de que todos mudem para Fragmentse usem setRetainInstance(true)os Fragmentque deseja manter.

Jon O
fonte
3
Eu realmente acho que Fragments e setRetainInstance são a melhor maneira (e recomendada pelo Google) de fazer isso, +1 para você e -1 para todos os outros. Adicionando android: configChanges só deve ser usada como último recurso
Simon Forsberg
32

A abordagem é útil, mas é incompleta ao usar fragmentos.

Fragmentos geralmente são recriados com alterações de configuração. Se você não deseja que isso aconteça, use

setRetainInstance(true); no (s) construtor (es) do fragmento

Isso fará com que fragmentos sejam retidos durante a alteração da configuração.

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

Abdo
fonte
7
Acordado. Com a mais recente API do Android, parece que os fragmentos são a maneira correta de lidar com isso. Eu ainda não tentei, mas pelo que reuni lendo esta página , você basicamente move 99% do que costumava implementar em uma atividade para uma subclasse de um fragmento e depois adiciona esse fragmento à atividade. A atividade ainda será destruída e recriada na rotação da tela, mas você pode dizer especificamente ao Android para não destruir o fragmento usando o setRetainInstance()método @Abdo mencionado.
Brianmearns
25

Eu simplesmente adicionei

     android:configChanges="keyboard|keyboardHidden|orientation"

no arquivo de manifesto e não adicionou nenhum onConfigurationChangedmétodo em minha atividade.

Portanto, toda vez que o teclado desliza para fora ou nada acontece .

bass.t
fonte
adicionado <application ...android:configChanges="keyboard|keyboardHidden|orientation">e está funcionando. Minhas configurações no build.gradle:minSdkVersion 15, compileSdkVersion 23, buildToolsVersion "23.0.2"
Junior Mayhé 21/02
19

O onCreatemétodo ainda é chamado mesmo quando você altera o orientationAndroid. Portanto, mover toda a funcionalidade pesada para esse método não ajudará você

ganesh krishnan
fonte
18

Coloque o código abaixo dentro da sua <activity>tag em Manifest.xml:

android:configChanges="screenLayout|screenSize|orientation"
Vaishali Sutariya
fonte
17
 onConfigurationChanged is called when the screen rotates. 
 (onCreate is no longer called when screen rotates due to manifest, see:  
 android:configChanges)

Que parte do manifesto diz "não ligue onCreate()"?

Além disso, documentos do Google dizem que para evitar o uso android:configChanges(exceto como último recurso) .... Mas, em seguida, os métodos alternativos que sugerem tudo DO uso android:configChanges.

Foi minha experiência que o emulador SEMPRE chama onCreate()após a rotação.
Mas os 1-2 dispositivos em que executo o mesmo código ... não. (Não sei por que haveria alguma diferença.)

Carol
fonte
16

É muito simples, basta seguir os seguintes passos:

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

Isso funciona para mim:

Nota: a orientação depende da sua solicitação

ManiTeja
fonte
15

As alterações a serem feitas no manifesto do Android são:

android:configChanges="keyboardHidden|orientation" 

As adições a serem feitas dentro da atividade são:

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();
    }
}
sumit pandey
fonte
15

Adicione esta linha ao seu manifesto: -

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

e este trecho da atividade: -

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

Existem várias maneiras de fazer isso:

Salvar estado da atividade

Você pode salvar o estado da atividade em 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);
}

e use o bundlepara restaurar o estado.

@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
    }
}

Lidar com as mudanças de orientação sozinho

Outra alternativa é lidar com as mudanças de orientação por conta própria. Mas isso não é considerado uma boa prática.

Adicione isso ao seu arquivo de manifesto.

android:configChanges="keyboardHidden|orientation"

para Android 3.2 e posterior:

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

Restringir rotação

Você também pode limitar sua atividade ao modo retrato ou paisagem para evitar a rotação.

Adicione isso à tag de atividade no seu arquivo de manifesto:

        android:screenOrientation="portrait"

Ou implemente isso programaticamente em sua atividade:

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

A maneira que eu encontrei de fazer isso é usar os onRestoreInstanceStatee os onSaveInstanceStateeventos para salvar algo na Bundle(mesmo se você não precisa de quaisquer variáveis salvos, basta colocar alguma coisa lá dentro para que o Bundlenão está vazia). Em seguida, no onCreatemétodo, verifique se Bundleestá vazio e, se estiver, faça a inicialização, se não estiver, faça-o.

Shaun
fonte
11

Mesmo que não seja "o modo Android", obtive resultados muito bons ao lidar com as alterações de orientação e simplesmente reposicionar os widgets em uma exibição para levar em consideração a orientação alterada. Isso é mais rápido do que qualquer outra abordagem, porque suas visualizações não precisam ser salvas e restauradas. Ele também fornece uma experiência mais integrada ao usuário, porque os widgets reposicionados são exatamente os mesmos widgets, apenas movidos e / ou redimensionados. Não apenas o estado do modelo, mas também o estado de exibição, podem ser preservados dessa maneira.

RelativeLayoutÀs vezes, pode ser uma boa opção para uma visão que precisa se reorientar de tempos em tempos. Você apenas fornece um conjunto de parâmetros de layout retrato e um conjunto de parâmetros de layout paisagístico, com diferentes regras de posicionamento relativo em cada um, para cada widget filho. Em seguida, no seu onConfigurationChanged()método, você passa o apropriado para uma setLayoutParams()chamada em cada filho. Se algum controle filho precisar ser reorientado internamente , basta chamar um método nesse filho para executar a reorientação. Da mesma forma, essa criança chama métodos em qualquer um de seus controles filhos que precisam de reorientação interna e assim por diante.

Carl
fonte
Eu adoraria ver algum código de exemplo disso, parece brilhante!
Henrique de Sousa
8

Toda vez que a tela é girada, a atividade aberta é concluída e onCreate () é chamado novamente.

1 Você pode fazer uma coisa para salvar o estado da atividade quando a tela é girada, de modo que, Você pode recuperar todos os itens antigos quando onCreate () da atividade é chamado novamente. Consulte este link

2) Se você deseja impedir o reinício da atividade, basta colocar as seguintes linhas no arquivo manifest.xml.

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

você precisa usar o método onSavedInstanceState para armazenar todo o valor em seu parâmetro é has has bundle

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

E use

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

recuperar e definir o valor para visualizar os objetos que manipula as rotações da tela

koteswara DK
fonte
Isso precisa do nível 22 da API.
Mohammad Afrashteh
6

Nota: eu posto esta resposta se alguém no futuro enfrentar o mesmo problema que eu. Para mim, a seguinte linha não era suficiente:

android:configChanges="orientation"

Quando eu girei a tela, o método `onConfigurationChanged (Configuration newConfig) não foi chamado.

Solução: eu também tive que adicionar "screenSize", mesmo que o problema tivesse a ver com a orientação. Portanto, no arquivo AndroidManifest.xml, adicione este:

android:configChanges="keyboardHidden|orientation|screenSize"

Em seguida, implemente o método onConfigurationChanged(Configuration newConfig)

iHank
fonte
5

Na seção de atividades do manifest, adicione:

android:configChanges="keyboardHidden|orientation"
Richard K Maleho
fonte
5

Adicione esta linha no manifesto: android:configChanges="orientation|screenSize"

Vikramsinh Gaikwad
fonte
4

As pessoas estão dizendo que você deveria usar

android:configChanges="keyboardHidden|orientation"

Mas a melhor e mais profissional maneira de lidar com a rotação no Android é usar a classe Loader. Não é uma aula famosa (não sei por quê), mas é muito melhor que o AsyncTask. Para obter mais informações, você pode ler os tutoriais para Android encontrados nos cursos para Android da Udacity.

Obviamente, como outra maneira, você pode armazenar os valores ou as visualizações com onSaveInstanceState e lê-los com onRestoreInstanceState. Depende de você mesmo.

Theo
fonte
Sim, vamos adicionar um monte de código extra para parecer "profissional". Ou que tal se ater à maneira rápida, fácil, verdadeira e tentada de fazê-lo com o atributo configurationChanges.
AndroidDev 19/05/19
3

Depois de um tempo de tentativa e erro, encontrei uma solução que se adapta às minhas necessidades na maioria das situações. Aqui está o código:

Configuração do manifesto:

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

Atividade principal:

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

}

E fragmento de amostra:

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

}

Pode ser encontrado no github .

Martin Pfeffer
fonte
3

Use o orientationouvinte para executar tarefas diferentes em diferentes orientações.

@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);
    }
}
Akshay Paliwal
fonte
3

Coloque este código abaixo na sua Activityem Android Manifest.

android:configChanges="orientation"

Isso não reiniciará sua atividade quando você alterar a orientação.

Pratik Dasa
fonte
2
@Mavamaarten Provavelmente porque, como outros já apontaram, é uma prática ruim e dez outras respostas já cobriram isso.
22714 MikkoP
3

Corrija a orientação da tela (paisagem ou retrato) em AndroidManifest.xml

android:screenOrientation="portrait" ou android:screenOrientation="landscape"

para isso, seu onResume()método não é chamado.

Brajendra Pandey
fonte
5
como diabos consertar algo é uma resposta? Por que nossos dispositivos podem girar se bloquearmos os usuários?
precisa saber é o seguinte
3

Um dos melhores componentes da arquitetura android introduzida pelo google cumprirá todos os requisitos exigidos pelo ViewModel.

Ele foi projetado para armazenar e gerenciar dados relacionados à interface do usuário no ciclo de vida, além de permitir que os dados sobrevivam à medida que a tela gira

class MyViewModel : ViewModel() {

Consulte o seguinte: https://developer.android.com/topic/libraries/architecture/viewmodel

Android Geek
fonte
1

Você pode usar o objeto ViewModel em sua atividade.

Os objetos ViewModel são retidos automaticamente durante as alterações na configuração, para que os dados que eles mantêm estejam imediatamente disponíveis para a próxima atividade ou instância de fragmento. Consulte Mais informação:

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

Gregory Buiko
fonte