Usando o pacote de compatibilidade para o destino 2.2 usando Fragmentos.
Depois de recodificar uma atividade para usar fragmentos em um aplicativo, não consegui que as mudanças de orientação / gerenciamento de estado funcionassem, por isso criei um pequeno aplicativo de teste com uma única FragmentActivity e um único fragmento.
Os logs das alterações de orientação são estranhos, com várias chamadas para os fragmentos OnCreateView.
Obviamente, estou perdendo algo - como desvendar o fragmento e anexá-lo novamente, em vez de criar uma nova instância, mas não consigo ver nenhuma documentação que indique onde estou errado.
Alguém pode esclarecer o que estou fazendo de errado aqui, por favor. obrigado
O log é o seguinte após as alterações de orientação.
Initial creation
12-04 11:57:15.808: D/FragmentTest.FragmentTestActivity(3143): onCreate
12-04 11:57:15.945: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:57:16.081: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState null
Orientation Change 1
12-04 11:57:39.031: D/FragmentTest.FragmentOne(3143): onSaveInstanceState
12-04 11:57:39.031: D/FragmentTest.FragmentTestActivity(3143): onCreate
12-04 11:57:39.031: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:57:39.031: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState not null
12-04 11:57:39.031: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:57:39.167: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState null
Orientation Change 2
12-04 11:58:32.162: D/FragmentTest.FragmentOne(3143): onSaveInstanceState
12-04 11:58:32.162: D/FragmentTest.FragmentOne(3143): onSaveInstanceState
12-04 11:58:32.361: D/FragmentTest.FragmentTestActivity(3143): onCreate
12-04 11:58:32.361: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:58:32.361: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState not null
12-04 11:58:32.361: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:58:32.361: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState not null
12-04 11:58:32.498: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:58:32.498: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState null
Atividade principal (FragmentActivity)
public class FragmentTestActivity extends FragmentActivity {
/** Called when the activity is first created. */
private static final String TAG = "FragmentTest.FragmentTestActivity";
FragmentManager mFragmentManager;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.d(TAG, "onCreate");
mFragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
FragmentOne fragment = new FragmentOne();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
}
E o fragmento
public class FragmentOne extends Fragment {
private static final String TAG = "FragmentTest.FragmentOne";
EditText mEditText;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d(TAG, "OnCreateView");
View v = inflater.inflate(R.layout.fragmentonelayout, container, false);
// Retrieve the text editor, and restore the last saved state if needed.
mEditText = (EditText)v.findViewById(R.id.editText1);
if (savedInstanceState != null) {
Log.d(TAG, "OnCreateView->SavedInstanceState not null");
mEditText.setText(savedInstanceState.getCharSequence("text"));
}
else {
Log.d(TAG,"OnCreateView->SavedInstanceState null");
}
return v;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.d(TAG, "FragmentOne.onSaveInstanceState");
// Remember the current text, to restore if we later restart.
outState.putCharSequence("text", mEditText.getText());
}
Manifesto
<uses-sdk android:minSdkVersion="8" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:label="@string/app_name"
android:name=".activities.FragmentTestActivity"
android:configChanges="orientation">
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
Respostas:
Você está colocando seus fragmentos em camadas um sobre o outro.
Quando ocorre uma alteração na configuração, o fragmento antigo se adiciona à nova atividade quando é recriada. É uma dor enorme na retaguarda na maioria das vezes.
Você pode interromper a ocorrência de erros usando o mesmo fragmento em vez de recriar um novo. Basta adicionar este código:
Entretanto, esteja avisado: ocorrerão problemas se você tentar acessar as Exibições de Atividade de dentro do Fragmento, pois os ciclos de vida serão alterados sutilmente. (Obter visualizações de um pai A atividade de um fragmento não é fácil).
fonte
"when the activity is destroyed, so are all fragments"
:? Desde então"When the screen orientation changes, the system destroys and recreates the activity [...]"
.Para citar este livro , "para garantir uma experiência consistente do usuário, o Android persiste no layout do Fragmento e na pilha traseira associada quando uma Atividade é reiniciada devido a uma alteração na configuração". (p. 124)
E a maneira de abordar isso é primeiro verificar se a pilha de trás do fragmento já foi preenchida e criar a nova instância de fragmento somente se não tiver:
fonte
O método onCreate () da sua atividade é chamado após a mudança de orientação, como você viu. Portanto, não execute a FragmentTransaction que adiciona o Fragment após a mudança de orientação em sua atividade.
Os fragmentos devem e devem ser inalterados.
fonte
Você pode
@Override
usar o FragmentActivityonSaveInstanceState()
. Certifique-se de não chamarsuper.onSaveInstanceState()
o método.fonte
Devemos sempre tentar evitar a exceção nullpointer, portanto, precisamos verificar primeiro no método saveinstance as informações do pacote. para uma breve explicação para verificar este link do blog
fonte
Na alteração da configuração, a estrutura criará uma nova instância do fragmento para você e a incluirá na atividade. Então, em vez disso:
faça isso:
Observe que a estrutura adiciona uma nova instância do FragmentOne na mudança de orientação, a menos que você chame setRetainInstance (true); nesse caso, ela adicionará a instância antiga do FragmentOne.
fonte
Se você acabou de fazer um projeto, o gerente do projeto diz que é necessário obter a tela de função de comutação, mas não deseja que a comutação de tela carregue um layout diferente (pode criar um sistema de layout e porta de layout.
Você determinará automaticamente o estado da tela, carregará o layout correspondente), devido à necessidade de reinicializar a atividade ou fragmento, a experiência do usuário não é boa, não diretamente na opção de tela, refiro-me? Url = YgNfP-vHy-Nuldi7YHTfNet3AtLdN-w__O3z1wLOnzr3wDjYo7X7PYdNyhw8R24ZE22xiKnydni7R0r35s2fOLcHOiLGYT9Qh_fjqtyt45ki19e0d1d0d0d0e0d0e0e1e1e0e05e03e1
A premissa é que seu layout use o peso da maneira como o layout do layout_weight, da seguinte maneira:
Portanto, minha abordagem é que, ao alternar a tela, não é necessário carregar um novo layout do arquivo de exibição, modificar o layout nos pesos dinâmicos onConfigurationChanged, as seguintes etapas: 1 primeiro conjunto: AndroidManifest.xml no atributo de atividade: android: configChanges = "keyboardHidden | orientação | screenSize" Para impedir a alternância de tela, evite recarregar, para poder monitorar a atividade de reescrita do onConfigurationChanged 2 ou o fragmento no método onConfigurationChanged.
fonte