122 votes

Android Fragment du cycle de vie des plus de changements d'orientation de l'

En utilisant le package de compatibilité à la cible 2.2, à l'aide de Fragments.

Après recodage d'une activité à utiliser des fragments dans une application que je ne pouvais pas obtenir les changements d'orientation/la gestion de l'état de travail, donc j'ai créé une petite application de test avec un seul FragmentActivity et un seul Fragment.

Les journaux de l'changements d'orientation sont bizarre, avec de multiples appels à l'fragments OnCreateView.

Je suis évidemment manque quelque chose - comme detatching le fragment et de remettre en place plutôt que de créer une nouvelle instance, mais je ne peux pas voir toute la documentation qui permettrait de savoir où je vais mal.

Quelqu'un peut jeter un peu de lumière sur ce que je fais mal ici s'il vous plaît. Merci

Le journal se présente comme suit, après les changements d'orientation.

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

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

Et le fragment

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

Manifeste

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

192voto

Graeme Points 9167

Vous êtes à la superposition de vos Fragments les uns sur les autres.

Quand une configuration changement se produit, l'ancien Fragment n'est pas détruit -- il ajoute lui-même de retour à l'Activité quand il est recréé. C'est une énorme douleur à l'arrière la plupart du temps.

Vous pouvez arrêter les erreurs qui se produisent en utilisant le même Fragment plutôt que de recréer un nouveau. Ajoutez simplement ce code:

if(savedInstanceState == null) 
{
    mFragmentManager = getSupportFragmentManager();
    FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();

    FragmentOne fragment = new FragmentOne();

    fragmentTransaction.add(R.id.fragment_container, fragment);
    fragmentTransaction.commit();
}

Soyez averti, cependant: les problèmes vont se produire si vous essayez d'accéder à l'Activité des Vues de l'intérieur du Fragment que les cycles de vie va légèrement modifier. (L'obtention de l'avis d'un parent de l'Activité à partir d'un Fragment n'est pas facile).

89voto

k29 Points 592

Pour citer ce livre, "afin d'assurer une expérience utilisateur cohérente, Android persiste le Fragment de mise en page et associés pile de retour lorsqu'un L'activité a redémarré en raison d'un changement de configuration." (p. 124)

Et la façon de l'aborder est de vérifier d'abord si le Fragment pile de retour a déjà été rempli, et de créer le nouveau fragment de l'instance que si elle n'a pas:

@Override
public void onCreate(Bundle savedInstanceState) {

        ...    

    FragmentOne fragment = (FragmentOne) mFragmentManager.findFragmentById(R.id.fragment_container); 

    if (fragment == null) {
        FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
        fragmentTransaction.add(R.id.fragment_container, new FragmentOne());
        fragmentTransaction.commit();
    }
}

10voto

Le onCreate() la méthode de votre activité est appelée après le changement d'orientation que vous avez vu. Donc, ne pas exécuter de la FragmentTransaction qui ajoute le Fragment après le changement d'orientation dans votre activité.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (savedInstanceState==null) {
        //do your stuff
    }
}

Les Fragments devrait et doit être inchangée.

4voto

Victor.Chan Points 39

vous pouvez overrider la FragmentActivity onSaveInstanceState() et ne pas appeler l' supder.onSaveInstanceState() dans la méthode.

0voto

abhishesh Points 260

Nous devrions toujours essayer de prévenir nullpointer exception , donc nous devons d'abord vérifier dans saveinstance méthode pour les bundle de l'information. pour une brève explication de vérifier ce lien de blog entrez description du lien ici

public static de la classe DetailsActivity s'étend de l'Activité {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if (getResources().getConfiguration().orientation
            == Configuration.ORIENTATION_LANDSCAPE) {
        // If the screen is now in landscape mode, we can show the
        // dialog in-line with the list so we don't need this activity.
        finish();
        return;
    }

    if (savedInstanceState == null) {
        // During initial setup, plug in the details fragment.
        DetailsFragment details = new DetailsFragment();
        details.setArguments(getIntent().getExtras());
        getFragmentManager().beginTransaction().add(android.R.id.content, details).commit();
    }
}

}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X