2012-09-28 2 views
97

Qu'est-ce exactement se produit lorsque vous appelez setRetainInstance(true) sur un Fragment? La documentation est pratiquement inexistante et cela semble être une fonction très importante. Plus précisément, je veux savoir combien de cette séquence (que je compose) est vrai:Pour mieux comprendre setRetainInstance (true)

  1. L'utilisateur fait tourner le dispositif. Le fragment est détaché du Activity et Fragment.onDetach() est appelé.
  2. L'activité est détruite; Activity.onDestroy() s'appelle.
  3. L'objet Java Activity est supprimé (si possible, par le CPG). Un nouvel objet Java Activity est créé; son constructeur, et onCreate() sont appelés.
  4. En Activity.onCreate() nous avons soit setContentView(...) qui définit une disposition contenant un fragment, ou nous utilisons FragmentTransaction pour ajouter un fragment.
  5. Je ne suis pas sûr, mais je suppose que Android est assez intelligent pour trouver le vieux fragment, et appeler à Fragment.onAttach() rattachez à la nouvelle Activity
  6. suivant (ou avant? Qui sait?) Activity.onResume() est appelé.

Est-ce correct? Android est-il assez intelligent pour trouver l'ancien fragment, même si j'utilise explicitement FragmentTransaction.add(new MyFragment(), ...) la première fois? Et si oui, comment éviter d'ajouter un autre fragment dans onCreate()? Est-ce que je dois faire quelque chose comme ça ?:

Répondre

86

Ok, peut-être que j'étais un peu trop dur sur la documentation Android, car elle contient des informations utiles, mais malheureusement, aucune n'est liée à setRetainInstance(). De the page about fragments

Note: Chaque fragment nécessite un identifiant unique que le système peut utiliser pour restaurer le fragment si l'activité redémarre (et qui vous pouvez utiliser pour capturer le fragment pour effectuer des transactions, telles que supprimer il). Il y a trois façons de fournir une pièce d'identité pour un fragment:

  • alimentation l'androïde: attribut id avec un identifiant unique.
  • Fournit l'attribut android: tag avec une chaîne unique.
  • Si vous ne fournissez aucun des deux précédents, le système utilise l'ID de la vue conteneur.

Cela implique fortement que si vous faites setContentView(R.layout.whatever) dans Activity.onCreated() et que la mise en page contient un fragment avec setRetainInstance(true), puis lorsque l'activité est recréée il sera recherché à nouveau en utilisant son identifiant ou une étiquette.

En second lieu, des fragments de l'interface utilisateur-moins, il déclare

Pour ajouter un fragment sans une interface utilisateur, ajoutez le fragment de l'activité à l'aide ajouter (Fragment, String) (fournissant une chaîne unique "tag" pour le fragment , plutôt qu'un ID de vue). Cela ajoute le fragment, mais, comme n'est pas associé à une vue dans la disposition d'activité, il ne reçoit pas d'appel à onCreateView() . Vous n'avez donc pas besoin de mettre en œuvre cette méthode .

Et les docs lien vers un très bon exemple - FragmentRetainInstance.java que j'ai reproduit ci-dessous pour votre commodité. Il fait exactement ce que j'ai spéculé était la réponse à ma question (if (...findFragmentByTag() == null) { ...).

Enfin, j'ai créé ma propre activité de test pour voir exactement quelles fonctions sont appelées. Il sort ceci, quand vous commencez en portrait et faites la rotation au paysage. Le code est ci-dessous.

(Ceci est édité un peu pour le rendre plus facile à lire.)

[email protected]: this() 
[email protected]: onCreate() 
[email protected]: Existing fragment not found. 
TestFragment{41583008}: this() TestFragment{41583008} 
TestFragment{41583008}: onAttach([email protected]) 
TestFragment{41583008}: onCreate() 
TestFragment{41583008}: onCreateView() 
TestFragment{41583008}: onActivityCreated() 
[email protected]: onStart() 
TestFragment{41583008}: onStart() 
[email protected]: onResume() 
TestFragment{41583008}: onResume() 

<rotate device> 

TestFragment{41583008}: onPause() 
[email protected]: onPause() 
TestFragment{41583008}: onStop() 
[email protected]: onStop() 
TestFragment{41583008}: onDestroyView() 
TestFragment{41583008}: onDetach() 
[email protected]: onDestroy() 
[email protected]: this() 
TestFragment{41583008}: onAttach([email protected]) 
[email protected]: onCreate() 
[email protected]: Existing fragment found. 
TestFragment{41583008}: onCreateView() 
TestFragment{41583008}: onActivityCreated() 
[email protected]: onStart() 
TestFragment{41583008}: onStart() 
[email protected]: onResume() 
TestFragment{41583008}: onResume() 

Notez que la documentation Android est erronée: le fragment de l'interface utilisateur-moins ne reçoivent un appel à onCreateView() mais il est libre de retourner null.

code source pour TestActivity/TestFragment

import android.app.Activity; 
import android.app.Fragment; 
import android.app.FragmentTransaction; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.TextView; 

import com.concentriclivers.ss.R; 

// An activity for understanding Android lifecycle events. 
public class TestActivity extends Activity 
{ 
    private static final String TAG = TestActivity.class.getSimpleName(); 

    public TestActivity() 
    { 
     super(); 
     Log.d(TAG, this + ": this()"); 
    } 

    protected void finalize() throws Throwable 
    { 
     super.finalize(); 
     Log.d(TAG, this + ": finalize()"); 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     Log.d(TAG, this + ": onCreate()"); 


     TextView tv = new TextView(this); 
     tv.setText("Hello world"); 
     setContentView(tv); 

     if (getFragmentManager().findFragmentByTag("test_fragment") == null) 
     { 
      Log.d(TAG, this + ": Existing fragment not found."); 
      FragmentTransaction ft = getFragmentManager().beginTransaction(); 
      ft.add(new TestFragment(), "test_fragment").commit(); 
     } 
     else 
     { 
      Log.d(TAG, this + ": Existing fragment found."); 
     } 
    } 

    @Override 
    public void onStart() 
    { 
     super.onStart(); 
     Log.d(TAG, this + ": onStart()"); 
    } 

    @Override 
    public void onResume() 
    { 
     super.onResume(); 
     Log.d(TAG, this + ": onResume()"); 
    } 

    @Override 
    public void onPause() 
    { 
     super.onPause(); 
     Log.d(TAG, this + ": onPause()"); 
    } 

    @Override 
    public void onStop() 
    { 
     super.onStop(); 
     Log.d(TAG, this + ": onStop()"); 
    } 

    @Override 
    public void onDestroy() 
    { 
     super.onDestroy(); 
     Log.d(TAG, this + ": onDestroy()"); 
    } 




    public static class TestFragment extends Fragment 
    { 
     private static final String TAG = TestFragment.class.getSimpleName(); 

     public TestFragment() 
     { 
      super(); 
      Log.d(TAG, this + ": this() " + this); 
     } 

     @Override 
     public void onCreate(Bundle savedInstanceState) 
     { 
      super.onCreate(savedInstanceState); 
      Log.d(TAG, this + ": onCreate()"); 
      setRetainInstance(true); 
     } 

     @Override 
     public void onAttach(final Activity activity) 
     { 
      super.onAttach(activity); 
      Log.d(TAG, this + ": onAttach(" + activity + ")"); 
     } 

     @Override 
     public void onActivityCreated(Bundle savedInstanceState) 
     { 
      super.onActivityCreated(savedInstanceState); 
      Log.d(TAG, this + ": onActivityCreated()"); 
     } 

     @Override 
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
     { 
      Log.d(TAG, this + ": onCreateView()"); 
      return null; 
     } 

     @Override 
     public void onViewCreated(View view, Bundle savedInstanceState) 
     { 
      super.onViewCreated(view, savedInstanceState); 
      Log.d(TAG, this + ": onViewCreated()"); 
     } 

     @Override 
     public void onDestroyView() 
     { 
      super.onDestroyView(); 
      Log.d(TAG, this + ": onDestroyView()"); 
     } 

     @Override 
     public void onDetach() 
     { 
      super.onDetach(); 
      Log.d(TAG, this + ": onDetach()"); 
     } 

     @Override 
     public void onStart() 
     { 
      super.onStart(); 
      Log.d(TAG, this + ": onStart()"); 
     } 

     @Override 
     public void onResume() 
     { 
      super.onResume(); 
      Log.d(TAG, this + ": onResume()"); 
     } 

     @Override 
     public void onPause() 
     { 
      super.onPause(); 
      Log.d(TAG, this + ": onPause()"); 
     } 

     @Override 
     public void onStop() 
     { 
      super.onStop(); 
      Log.d(TAG, this + ": onStop()"); 
     } 

     @Override 
     public void onDestroy() 
     { 
      super.onDestroy(); 
      Log.d(TAG, this + ": onDestroy()"); 
     } 
    } 

} 

code source pour FragmentRetainInstance.java (comme l'API 16):

/* 
* Copyright (C) 2010 The Android Open Source Project 
* 
* Licensed under the Apache License, Version 2.0 (the "License"); 
* you may not use this file except in compliance with the License. 
* You may obtain a copy of the License at 
* 
*  http://www.apache.org/licenses/LICENSE-2.0 
* 
* Unless required by applicable law or agreed to in writing, software 
* distributed under the License is distributed on an "AS IS" BASIS, 
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
* See the License for the specific language governing permissions and 
* limitations under the License. 
*/ 

package com.example.android.apis.app; 

import com.example.android.apis.R; 

import android.app.Activity; 
import android.app.Fragment; 
import android.app.FragmentManager; 
import android.os.Bundle; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.view.View.OnClickListener; 
import android.widget.Button; 
import android.widget.ProgressBar; 

/** 
* This example shows how you can use a Fragment to easily propagate state 
* (such as threads) across activity instances when an activity needs to be 
* restarted due to, for example, a configuration change. This is a lot 
* easier than using the raw Activity.onRetainNonConfiguratinInstance() API. 
*/ 
public class FragmentRetainInstance extends Activity { 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     // First time init, create the UI. 
     if (savedInstanceState == null) { 
      getFragmentManager().beginTransaction().add(android.R.id.content, 
        new UiFragment()).commit(); 
     } 
    } 

    /** 
    * This is a fragment showing UI that will be updated from work done 
    * in the retained fragment. 
    */ 
    public static class UiFragment extends Fragment { 
     RetainedFragment mWorkFragment; 

     @Override 
     public View onCreateView(LayoutInflater inflater, ViewGroup container, 
       Bundle savedInstanceState) { 
      View v = inflater.inflate(R.layout.fragment_retain_instance, container, false); 

      // Watch for button clicks. 
      Button button = (Button)v.findViewById(R.id.restart); 
      button.setOnClickListener(new OnClickListener() { 
       public void onClick(View v) { 
        mWorkFragment.restart(); 
       } 
      }); 

      return v; 
     } 

     @Override 
     public void onActivityCreated(Bundle savedInstanceState) { 
      super.onActivityCreated(savedInstanceState); 

      FragmentManager fm = getFragmentManager(); 

      // Check to see if we have retained the worker fragment. 
      mWorkFragment = (RetainedFragment)fm.findFragmentByTag("work"); 

      // If not retained (or first time running), we need to create it. 
      if (mWorkFragment == null) { 
       mWorkFragment = new RetainedFragment(); 
       // Tell it who it is working with. 
       mWorkFragment.setTargetFragment(this, 0); 
       fm.beginTransaction().add(mWorkFragment, "work").commit(); 
      } 
     } 

    } 

    /** 
    * This is the Fragment implementation that will be retained across 
    * activity instances. It represents some ongoing work, here a thread 
    * we have that sits around incrementing a progress indicator. 
    */ 
    public static class RetainedFragment extends Fragment { 
     ProgressBar mProgressBar; 
     int mPosition; 
     boolean mReady = false; 
     boolean mQuiting = false; 

     /** 
     * This is the thread that will do our work. It sits in a loop running 
     * the progress up until it has reached the top, then stops and waits. 
     */ 
     final Thread mThread = new Thread() { 
      @Override 
      public void run() { 
       // We'll figure the real value out later. 
       int max = 10000; 

       // This thread runs almost forever. 
       while (true) { 

        // Update our shared state with the UI. 
        synchronized (this) { 
         // Our thread is stopped if the UI is not ready 
         // or it has completed its work. 
         while (!mReady || mPosition >= max) { 
          if (mQuiting) { 
           return; 
          } 
          try { 
           wait(); 
          } catch (InterruptedException e) { 
          } 
         } 

         // Now update the progress. Note it is important that 
         // we touch the progress bar with the lock held, so it 
         // doesn't disappear on us. 
         mPosition++; 
         max = mProgressBar.getMax(); 
         mProgressBar.setProgress(mPosition); 
        } 

        // Normally we would be doing some work, but put a kludge 
        // here to pretend like we are. 
        synchronized (this) { 
         try { 
          wait(50); 
         } catch (InterruptedException e) { 
         } 
        } 
       } 
      } 
     }; 

     /** 
     * Fragment initialization. We way we want to be retained and 
     * start our thread. 
     */ 
     @Override 
     public void onCreate(Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState); 

      // Tell the framework to try to keep this fragment around 
      // during a configuration change. 
      setRetainInstance(true); 

      // Start up the worker thread. 
      mThread.start(); 
     } 

     /** 
     * This is called when the Fragment's Activity is ready to go, after 
     * its content view has been installed; it is called both after 
     * the initial fragment creation and after the fragment is re-attached 
     * to a new activity. 
     */ 
     @Override 
     public void onActivityCreated(Bundle savedInstanceState) { 
      super.onActivityCreated(savedInstanceState); 

      // Retrieve the progress bar from the target's view hierarchy. 
      mProgressBar = (ProgressBar)getTargetFragment().getView().findViewById(
        R.id.progress_horizontal); 

      // We are ready for our thread to go. 
      synchronized (mThread) { 
       mReady = true; 
       mThread.notify(); 
      } 
     } 

     /** 
     * This is called when the fragment is going away. It is NOT called 
     * when the fragment is being propagated between activity instances. 
     */ 
     @Override 
     public void onDestroy() { 
      // Make the thread go away. 
      synchronized (mThread) { 
       mReady = false; 
       mQuiting = true; 
       mThread.notify(); 
      } 

      super.onDestroy(); 
     } 

     /** 
     * This is called right before the fragment is detached from its 
     * current activity instance. 
     */ 
     @Override 
     public void onDetach() { 
      // This fragment is being detached from its activity. We need 
      // to make sure its thread is not going to touch any activity 
      // state after returning from this function. 
      synchronized (mThread) { 
       mProgressBar = null; 
       mReady = false; 
       mThread.notify(); 
      } 

      super.onDetach(); 
     } 

     /** 
     * API for our UI to restart the progress thread. 
     */ 
     public void restart() { 
      synchronized (mThread) { 
       mPosition = 0; 
       mThread.notify(); 
      } 
     } 
    } 
} 
+0

Pourriez-vous examiner ma question et me dire comment j'implémenterais votre solution? Mon application fonctionne mais je veux supprimer android: configChanges = "orientation | keyboardHidden | screenSize" et l'application ne pourra pas conserver son écouteur de fragmentation après le changement de configuration. http://stackoverflow.com/questions/35941585/avoiding-manually-handling-configuration-changes –

40

setRetainInstance() dans Fragment classe est un remplacement intelligent pour onRetainCustomNonConfigurationInstance() de Activity classe, et plus encore.

Clairement indiqué in the documentation.

est ici Connectez-vous de ce qui se passe (Un fragment de l'interface utilisateur ajouter à la demande et un changement de configuration):

Par défaut setRetainInstance(false)

09-29 13:23:04.771: DEBUG/szipinf(4790): Initializing inflate state 
09-29 13:23:04.801: INFO/TESTING - MYACTIVITY(4790): Instantiated - [email protected] 
09-29 13:23:04.851: DEBUG/dalvikvm(4790): GC_EXTERNAL_ALLOC freed 49K, 51% free 2686K/5379K, external 0K/0K, paused 45ms 
09-29 13:23:04.881: INFO/TESTING - MYACTIVITY(4790): onCreate - [email protected] 
09-29 13:23:04.881: INFO/TESTING - MYACTIVITY(4790): onStart - [email protected] 
09-29 13:23:04.881: INFO/TESTING - MYACTIVITY(4790): onResume - [email protected] 
09-29 13:23:04.891: INFO/TESTING - MYACTIVITY(4790): onAttachedToWindow - [email protected] 
09-29 13:23:10.381: DEBUG/dalvikvm(4457): GC_EXPLICIT freed 8K, 51% free 2681K/5379K, external 0K/0K, paused 38ms 
09-29 13:23:11.901: INFO/TESTING - MYFRAGMENT(4790): Instantiated - MyFragment{40530610} 
09-29 13:23:11.911: INFO/TESTING - MYFRAGMENT(4790): onAttach - MyFragment{40530610 #0 MyFragment} 
09-29 13:23:11.911: INFO/TESTING - MYACTIVITY(4790): onAttachFragment - [email protected] 
09-29 13:23:11.911: INFO/TESTING - MYFRAGMENT(4790): onCreate - MyFragment{40530610 #0 MyFragment} 
09-29 13:23:11.911: INFO/TESTING - MYFRAGMENT(4790): onCreateView - MyFragment{40530610 #0 MyFragment} 
09-29 13:23:11.921: INFO/TESTING - MYFRAGMENT(4790): onViewCreated - MyFragment{40530610 #0 MyFragment} 
09-29 13:23:11.921: INFO/TESTING - MYFRAGMENT(4790): onActivityCreated - MyFragment{40530610 #0 MyFragment} 
09-29 13:23:11.931: INFO/TESTING - MYFRAGMENT(4790): onStart - MyFragment{40530610 #0 MyFragment} 
09-29 13:23:11.931: INFO/TESTING - MYFRAGMENT(4790): onResume - MyFragment{40530610 #0 MyFragment} 
09-29 13:23:15.081: INFO/ActivityManager(1268): Config changed: { scale=1.0 imsi=404/45 loc=en_US touch=3 keys=1/1/2 nav=1/1 orien=2 layout=34 uiMode=17 seq=105 themeResource=null} 
09-29 13:23:15.111: INFO/TESTING - MYACTIVITY(4790): onSaveInstanceState - [email protected] 
09-29 13:23:15.111: INFO/TESTING - MYFRAGMENT(4790): onPause - MyFragment{40530610 #0 MyFragment} 
09-29 13:23:15.121: INFO/TESTING - MYACTIVITY(4790): onPause - [email protected] 
09-29 13:23:15.121: INFO/TESTING - MYFRAGMENT(4790): onStop - MyFragment{40530610 #0 MyFragment} 
09-29 13:23:15.121: INFO/TESTING - MYACTIVITY(4790): onStop - [email protected] 
09-29 13:23:15.121: INFO/TESTING - MYACTIVITY(4790): onRetainCustomNonConfigurationInstance - [email protected] 
09-29 13:23:15.121: INFO/TESTING - MYFRAGMENT(4790): onDestroyView - MyFragment{40530610 #0 MyFragment} 
09-29 13:23:15.121: INFO/TESTING - MYFRAGMENT(4790): onDestroy - MyFragment{40530610 #0 MyFragment} 
09-29 13:23:15.121: INFO/TESTING - MYFRAGMENT(4790): onDetach - MyFragment{40530610 #0 MyFragment} 
09-29 13:23:15.121: INFO/TESTING - MYACTIVITY(4790): onDestroy - [email protected] 
09-29 13:23:15.191: INFO/TESTING - MYACTIVITY(4790): onDetachedFromWindow - [email protected] 
09-29 13:23:15.201: INFO/TESTING - MYACTIVITY(4790): Instantiated - [email protected] 
09-29 13:23:15.201: INFO/TESTING - MYFRAGMENT(4790): Instantiated - MyFragment{4053cde0} 
09-29 13:23:15.201: INFO/TESTING - MYFRAGMENT(4790): onAttach - MyFragment{4053cde0 #0 MyFragment} 
09-29 13:23:15.201: INFO/TESTING - MYACTIVITY(4790): onAttachFragment - [email protected] 
09-29 13:23:15.201: INFO/TESTING - MYFRAGMENT(4790): onCreate - MyFragment{4053cde0 #0 MyFragment} 
09-29 13:23:15.251: INFO/TESTING - MYACTIVITY(4790): onCreate - [email protected] 
09-29 13:23:15.251: INFO/TESTING - MYFRAGMENT(4790): onCreateView - MyFragment{4053cde0 #0 MyFragment} 
09-29 13:23:15.261: INFO/TESTING - MYFRAGMENT(4790): onViewCreated - MyFragment{4053cde0 #0 MyFragment} 
09-29 13:23:15.261: INFO/TESTING - MYFRAGMENT(4790): onActivityCreated - MyFragment{4053cde0 #0 MyFragment} 
09-29 13:23:15.291: INFO/TESTING - MYFRAGMENT(4790): onStart - MyFragment{4053cde0 #0 MyFragment} 
09-29 13:23:15.291: INFO/TESTING - MYACTIVITY(4790): onStart - [email protected] 
09-29 13:23:15.291: INFO/TESTING - MYACTIVITY(4790): onResume - [email protected] 
09-29 13:23:15.291: INFO/TESTING - MYFRAGMENT(4790): onResume - MyFragment{4053cde0 #0 MyFragment} 
09-29 13:23:15.321: INFO/TESTING - MYACTIVITY(4790): onAttachedToWindow - [email protected] 

Ainsi, fragmenter est recréé tout nouveau, et montré à nouveau, tout cela en setRetainInstance(false)

Et maintenant, avec setRetainInstance(true)

09-29 13:18:46.121: INFO/ActivityManager(1268): Starting: Intent { flg=0x10100000 cmp=com.example/.MyActivity } from pid 1268 
09-29 13:18:46.141: INFO/TESTING - MYACTIVITY(4726): Instantiated - [email protected] 
09-29 13:18:46.161: INFO/TESTING - MYACTIVITY(4726): onCreate - [email protected] 
09-29 13:18:46.161: INFO/TESTING - MYACTIVITY(4726): onStart - [email protected] 
09-29 13:18:46.161: INFO/TESTING - MYACTIVITY(4726): onResume - [email protected] 
09-29 13:18:46.191: INFO/TESTING - MYACTIVITY(4726): onAttachedToWindow - [email protected] 
09-29 13:19:10.431: DEBUG/SntpClient(1268): request time failed: java.net.UnknownHostException: europe.pool.ntp.org 
09-29 13:19:14.251: INFO/TESTING - MYFRAGMENT(4726): Instantiated - MyFragment{405288c0} 
09-29 13:19:14.271: INFO/TESTING - MYFRAGMENT(4726): onAttach - MyFragment{405288c0 #0 MyFragment} 
09-29 13:19:14.271: INFO/TESTING - MYACTIVITY(4726): onAttachFragment - [email protected] 
09-29 13:19:14.271: INFO/TESTING - MYFRAGMENT(4726): onCreate - MyFragment{405288c0 #0 MyFragment} 
09-29 13:19:14.281: INFO/TESTING - MYFRAGMENT(4726): onCreateView - MyFragment{405288c0 #0 MyFragment} 
09-29 13:19:14.281: INFO/TESTING - MYFRAGMENT(4726): onViewCreated - MyFragment{405288c0 #0 MyFragment} 
09-29 13:19:14.281: INFO/TESTING - MYFRAGMENT(4726): onActivityCreated - MyFragment{405288c0 #0 MyFragment} 
09-29 13:19:14.291: INFO/TESTING - MYFRAGMENT(4726): onStart - MyFragment{405288c0 #0 MyFragment} 
09-29 13:19:14.291: INFO/TESTING - MYFRAGMENT(4726): onResume - MyFragment{405288c0 #0 MyFragment} 
09-29 13:19:21.921: INFO/ActivityManager(1268): Config changed: { scale=1.0 imsi=404/45 loc=en_US touch=3 keys=1/1/2 nav=1/1 orien=2 layout=34 uiMode=17 seq=103 themeResource=null} 
09-29 13:19:21.961: INFO/TESTING - MYACTIVITY(4726): onSaveInstanceState - [email protected] 
09-29 13:19:21.961: INFO/TESTING - MYFRAGMENT(4726): onPause - MyFragment{405288c0 #0 MyFragment} 
09-29 13:19:21.961: INFO/TESTING - MYACTIVITY(4726): onPause - [email protected] 
09-29 13:19:21.961: INFO/TESTING - MYFRAGMENT(4726): onStop - MyFragment{405288c0 #0 MyFragment} 
09-29 13:19:21.961: INFO/TESTING - MYACTIVITY(4726): onStop - [email protected] 
09-29 13:19:21.961: INFO/TESTING - MYACTIVITY(4726): onRetainCustomNonConfigurationInstance - [email protected] 
09-29 13:19:21.961: INFO/TESTING - MYFRAGMENT(4726): onDestroyView - MyFragment{405288c0 #0 MyFragment} 
09-29 13:19:21.961: INFO/TESTING - MYFRAGMENT(4726): onDetach - MyFragment{405288c0 #0 MyFragment} 
09-29 13:19:21.961: INFO/TESTING - MYACTIVITY(4726): onDestroy - [email protected] 
09-29 13:19:22.111: INFO/TESTING - MYACTIVITY(4726): onDetachedFromWindow - [email protected] 
09-29 13:19:22.111: INFO/TESTING - MYACTIVITY(4726): Instantiated - [email protected] 
09-29 13:19:22.111: INFO/TESTING - MYFRAGMENT(4726): onAttach - MyFragment{405288c0 #0 MyFragment} 
09-29 13:19:22.111: INFO/TESTING - MYACTIVITY(4726): onAttachFragment - [email protected] 
09-29 13:19:22.131: INFO/TESTING - MYACTIVITY(4726): onCreate - [email protected] 
09-29 13:19:22.131: INFO/TESTING - MYFRAGMENT(4726): onCreateView - MyFragment{405288c0 #0 MyFragment} 
09-29 13:19:22.131: INFO/TESTING - MYFRAGMENT(4726): onViewCreated - MyFragment{405288c0 #0 MyFragment} 
09-29 13:19:22.131: INFO/TESTING - MYFRAGMENT(4726): onActivityCreated - MyFragment{405288c0 #0 MyFragment} 
09-29 13:19:22.141: INFO/TESTING - MYFRAGMENT(4726): onStart - MyFragment{405288c0 #0 MyFragment} 
09-29 13:19:22.141: INFO/TESTING - MYACTIVITY(4726): onStart - [email protected] 
09-29 13:19:22.141: INFO/TESTING - MYACTIVITY(4726): onResume - [email protected] 
09-29 13:19:22.141: INFO/TESTING - MYFRAGMENT(4726): onResume - MyFragment{405288c0 #0 MyFragment} 
09-29 13:19:22.171: INFO/TESTING - MYACTIVITY(4726): onAttachedToWindow - [email protected] 
09-29 13:19:22.181: INFO/TESTING - MYFRAGMENT(4726): onPause - MyFragment{405288c0 #0 MyFragment} 
09-29 13:19:22.181: INFO/TESTING - MYFRAGMENT(4726): onStop - MyFragment{405288c0 #0 MyFragment} 
09-29 13:19:22.181: INFO/TESTING - MYFRAGMENT(4726): onDestroyView - MyFragment{405288c0 #0 MyFragment} 
09-29 13:19:22.181: INFO/TESTING - MYFRAGMENT(4726): onDestroy - MyFragment{405288c0 #0 MyFragment} 
09-29 13:19:22.181: INFO/TESTING - MYFRAGMENT(4726): onDetach - MyFragment{405288c0 #0 MyFragment} 

Vous avez noté l'effet? L'instance de fragment (objet 405288c0) a été conservée ce qui est bien. Mais l'instance retenue est très susceptible de contenir des ressources et des vues et des objets qui appartenaient à des orientations précédentes, ce qui peut entraîner des fuites de mémoire.

Il faut faire très attention lorsque vous écrivez le code pour lancer ce fragment: vous devez toujours vérifier s'il existe une instance préexistante.

Morale de l'histoire: setRetainInstance() est mieux utilisé pour les fragments non visuels.

+0

deux journaux me donnent la réponse .. Tout d'abord journal créer nouvelle instance à chaque fois (40530610,4053cde0), Après setRetainInstance() une seule instance 405288c0 –

Questions connexes