Pergunta

Na minha aplicação Android, quando eu rodar o dispositivo (deslizar para fora o teclado), então minha Activity é reiniciado (onCreate é chamado). Agora, esta é provavelmente assim que deveria ser, mas eu fazer um monte de configuração inicial no método onCreate, então eu preciso tanto:

  1. Coloque toda a configuração inicial em outra função, então não é todos perdidos na rotação do dispositivo ou
  2. Faça isso onCreate não é chamado novamente e o layout apenas ajusta ou
  3. Limite o app apenas retrato de modo que onCreate não é chamado.
Foi útil?

Solução

Usando a classe aplicativo

Dependendo do que você está fazendo em sua inicialização você poderia considerar a criação de uma nova classe que estende Application e movendo o código de inicialização em um método onCreate 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 na classe aplicação só é chamado quando o aplicativo inteiro é criado, então as Atividade reinicia na orientação ou de visibilidade teclado alterações não provocá-lo.

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

NOTA: Você precisa especificar o nome da sua nova classe de aplicações no manifesto para que possa ser registrado e usado:

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

Reagindo a alterações de configuração [UPDATE: este está obsoleto desde API 13; ver a alternativa recomendada ]

Como uma alternativa adicional, você pode ter seu aplicativo escutar eventos que poderiam causar um reinício - como orientação e visibilidade teclado mudanças -. E tratá-los dentro de sua atividade

Comece adicionando o nó android:configChanges ao nó manifesto do seu Activity

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

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

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

Em seguida, dentro da atividade substituir o método onConfigurationChanged e chamada setContentView para forçar o layout GUI para estar na nova orientação re-feito.

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

Outras dicas

Atualização para o Android 3.2 e superior:

Atenção : Começando com Android 3.2 (nível API 13), o "tamanho da tela" também muda quando o dispositivo alterna entre orientação retrato e paisagem. Assim, se você quer evitar de tempo de execução é reiniciado devido à mudança de orientação ao desenvolver para o nível de API 13 ou superior (conforme declarado pelo minSdkVersion e targetSdkVersion atributos), você deve incluir o valor "screenSize" além do valor "orientation". Ou seja, você deve declarar android:configChanges="orientation|screenSize". No entanto, se suas metas de aplicação de nível API 12 ou inferior, então a sua actividade sempre lida com essa própria mudança de configuração (essa alteração de configuração não reinicia sua atividade, mesmo quando rodando em um Android 3.2 ou superior do dispositivo).

Em vez de tentar parar o onCreate() de ser demitido por completo, talvez tente verificar a Bundle savedInstanceState sendo passado para o evento para ver se ele é nulo ou não.

Por exemplo, se eu tiver alguma lógica que deve ser executado quando o Activity é realmente criado, não em cada mudança de orientação, eu só executar essa lógica na onCreate() somente se o savedInstanceState é nulo.

Caso contrário, eu ainda quero o layout para redesenhar 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 esta é a resposta definitiva, mas funciona para mim.

o que eu fiz ...

no manifesto, para a seção de atividade, acrescentou:

android:configChanges="keyboardHidden|orientation"

no código para a atividade, implementada:

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

O que você descreve é ??o comportamento padrão. Você tem de detectar e lidar com esses eventos você mesmo adicionando:

android:configChanges

para o seu manifesto e, em seguida, as mudanças que você deseja manipular. Assim, para orientação, você usaria:

android:configChanges="orientation"

e para o teclado que está sendo aberto ou fechado, você usaria:

android:configChanges="keyboardHidden"

Se você quiser lidar com ambos você pode apenas separá-los com o comando tubo como:

android:configChanges="keyboardHidden|orientation"

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

Espero que isso ajude.

Eu só descobri este lore:

Para manter a Atividade vivo através de uma mudança de orientação, e manuseá-lo através onConfigurationChanged, a documentação e o exemplo de código acima sugerir este no arquivo de manifesto:

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

que tem a vantagem extra que sempre funciona.

O lore bônus é que omitindo o keyboardHidden pode parecer lógico, mas provoca falhas no emulador (para Android 2.1 pelo menos): especificando única orientation fará a chamada emulador tanto OnCreate e onConfigurationChanged às vezes, e apenas OnCreate outras vezes.

Eu não vi a falha em um dispositivo, mas eu ouvi sobre o emulador não para os outros. Assim vale a pena documentar.

Você também pode considerar o uso caminho da plataforma Android da persistência de dados em toda a orientação muda:. onRetainNonConfigurationInstance() e getLastNonConfigurationInstance()

Isso permite que você persistir dados através de alterações de configuração, tais como informações que você pode ter começado a partir de um servidor de busca ou qualquer outra coisa que tem sido calculado em onCreate ou uma vez que, ao mesmo tempo, permitindo que o Android para re-layout de seu Activity usando o arquivo xml para a orientação agora em uso.

aqui ou aqui .

Deve-se notar que esses métodos estão agora obsoleta (embora ainda mais flexível do que lidar com a mudança de orientação a si mesmo como a maioria das soluções acima sugerem), com a recomendação de que todos interruptor para Fragments e passar a usar setRetainInstance(true) em cada Fragment você deseja manter .

A abordagem é útil, mas é incompleta quando utilizar Fragmentos.

Fragmentos geralmente são recriados na alteração de configuração. Se você não deseja que isso aconteça, o uso

setRetainInstance(true); no construtor do Fragmento (s)

Isto fará com que os fragmentos que devem ser conservados durante a mudança de configuração.

http://developer.android.com/ referência / android / app / Fragment.html # setRetainInstance (boolean)

Eu simplesmente adicionado

     android:configChanges="keyboard|keyboardHidden|orientation"

no arquivo de manifesto e não adicionar qualquer método onConfigurationChanged na minha actividade.

Então, toda vez os slides teclado para fora ou em nada acontece .

O método onCreate ainda é chamado, mesmo quando você mudar o orientation do Android. Então, movendo todo o heavy funcionalidade para este método não vai ajudá-lo

É muito simples, basta fazer os seguintes passos:

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

Isso funciona para mim:

Nota: orientação depende da sua requitement

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

android:configChanges="screenLayout|screenSize|orientation"
 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 que "não chamar onCreate()"?

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

Tem sido minha experiência que o emulador sempre chama onCreate() mediante rotação.
Mas os 1-2 dispositivos que executam o mesmo código no ... não. (Não sei por que não haveria qualquer diferença.)

Adicione esta linha ao seu manifesto: -

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

e esse trecho para a atividade: -

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

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

android:configChanges="keyboardHidden|orientation" 

As adições a ser feita dentro 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();
    }
}

Existem várias maneiras de fazer isso:

Salvar Atividade Estado

Você pode salvar o estado de 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, em seguida, usar o bundle para 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
    }
}

orientação lidar com as mudanças por si mesmo

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

Adicione isto a sua 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 para o modo retrato ou paisagem à rotação evitar.

Adicione esta à tag de atividade em seu arquivo de manifesto:

        android:screenOrientation="portrait"

Ou implementar isso programaticamente em sua atividade:

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

A maneira que eu encontrei de fazer isso é usar o onRestoreInstanceState e os eventos onSaveInstanceState para salvar alguma coisa no Bundle (mesmo se você não precisa de quaisquer variáveis ??salvas, basta colocar alguma coisa lá dentro para que o Bundle não está vazia). Em seguida, no método onCreate, verificar para ver se o Bundle está vazio, e se for, em seguida, fazer a inicialização, se não, então fazê-lo.

Mesmo que ele não é "o caminho Android" Tenho obtido bons resultados pela manipulação orientação muda-me e simplesmente reposicionar os widgets dentro de uma visão para tomar a orientação alterada em conta. Isso é mais rápido do que qualquer outra abordagem, porque os seus pontos de vista não tem que ser salvo e restaurado. Ele também fornece uma experiência mais transparente para o usuário, porque os widgets respositioned são exatamente os mesmos widgets, acabou de se mudar e / ou redimensionadas. Não só estado do modelo, mas também exibição de estado, pode ser preservada desta maneira.

RelativeLayout às vezes pode ser uma boa escolha para uma visão que tem de reorientar-se de vez em quando. Você apenas fornecer um conjunto de parâmetros de layout retrato e um conjunto de parâmetros de layout paisagísticos, com diferentes regras de posicionamento relativo em cada, para cada widget filho. Então, em seu método onConfigurationChanged(), você passa o mais adequado para uma chamada setLayoutParams() em cada criança. Se qualquer próprio controle criança precisa ser internamente reorientadas, basta chamar um método em que a criança para realizar a reorientação. Aquela criança chama semelhante métodos em qualquer um dos sua controles filho que precisam de reorientação interna, e assim por diante.

Toda vez que quando a tela é girada, atividade aberta está terminado e onCreate () é chamado novamente.

1. Você pode fazer uma coisa salvar o estado da atividade quando a tela é girada para que, você pode recuperar todo o material de idade quando onCreate da atividade () é chamado novamente. Consulte este link

2. Se você quer evitar o reinício da atividade basta colocar seguintes linhas no seu arquivo manifest.xml.

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

Nota: eu postar esta resposta se alguém na cara futuro o mesmo problema que eu. Para mim a seguinte linha não foi enought:

android:configChanges="orientation"

Quando eu rodado o ecrã, o método `onConfigurationChanged (Configuração newconfig) did't obter chamado.

Solução: Eu também tive que adicionar "screensize", mesmo que o problema tinha a ver com a orientação. Assim, no AndroidManifest.xml - arquivo, adicione o seguinte:

android:configChanges="keyboardHidden|orientation|screenSize"

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

você precisa usar o método onSavedInstanceState para armazenar todo o valor para o parâmetro for tem que é pacote

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

e utilização

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

retrive e defina o valor para exibir objetos ele vai lida com a rotação de tela

Na seção do manifest atividade, adicione:

android:configChanges="keyboardHidden|orientation"

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

As pessoas estão dizendo que você deve usar

android:configChanges="keyboardHidden|orientation"

Mas a melhor e mais profissional maneira de rotação de punho no Android é usar a classe Loader. Não é uma classe famoso (não sei porquê), mas é muito melhor do que o AsyncTask. Para mais informações, você pode ler os tutoriais Android encontrados em cursos Android de Udacity.

Claro que, como uma outra maneira, você pode armazenar os valores ou os pontos de vista com onSaveInstanceState e lê-los com onRestoreInstanceState. É até você realmente.

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

manifesto de configuração:

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

}

E amostra Fragmento:

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 na github .

Use ouvinte orientation para executar diferentes tarefas na orientação diferente.

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

Coloque este código abaixo na sua Activity em Android Manifest.

android:configChanges="orientation"

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

Corrigir a orientação da tela (horizontal ou vertical) em AndroidManifest.xml

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

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

Um dos melhores componentes de architechure android introduzir by google vai cumprir o seu toda a exigência de que é ViewModel.

Isso é projetado para armazenar e gerenciar UI dados relacionados em forma de ciclo de vida mais que permitirá dados para sobreviver como gira tela

class MyViewModel : ViewModel() {

Por favor, consulte o seguinte: https://developer.android.com/topic/libraries / arquitectura / viewmodel

Você pode bloquear a orientação atual da tela usando este código ...

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);
        }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top