进一步了解setRetainInstance(true)

当你在一个Fragment上调用setRetainInstance(true)究竟发生了什么? 文档几乎是不存在的,这似乎是一个非常重要的function。 具体而言,我想知道这个序列(我编造的)有多less是正确的:

  1. 用户旋转设备。
  2. 该片段与Activity分离,并调用Fragment.onDetach()
  3. 活动被破坏; Activity.onDestroy()被调用。
  4. Activity java对象被删除(如果可能的话,由GC)。
  5. 一个新的Activity java对象被创build; 它的构造函数和onCreate()被调用。
  6. Activity.onCreate()我们要么有setContentView(...)来设置一个包含片段的布局,要么我们使用FragmentTransaction来添加一个片段。
  7. 我真的不知道这一点,但我认为Android智能足以find旧的片段,并调用Fragment.onAttach()重新附加到新的Activity
  8. 接下来(或之前?谁知道?) Activity.onResume()被调用。

那是对的吗? 即使我第一次显式地使用FragmentTransaction.add(new MyFragment(), ...) ,Android是否足够聪明地find旧的片段? 如果是这样,我怎么避免在onCreate()添加另一个片段? 我需要做这样的事吗?

  if (getSupportFragmentManager().findFragmentByTag("foo") == null) { FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.add(new FooFragment(), "foo").commit(); } 

为什么没有在文档中的这一点? 哈不,只是开玩笑,不要回答!

好的,也许我对Android文档有点太苛刻了,因为它确实有一些有用的信息,但遗憾的是它们中没有一个是从setRetainInstance()链接的。 从关于片段的页面

注意:每个片段都需要一个唯一的标识符,系统可以使用该标识符在活动重新启动时恢复片段(您可以使用该标识符来捕获片段以执行事务,例如删除它)。 有三种方法可以为片段提供ID:

  • 提供具有唯一ID的android:id属性。
  • 提供具有唯一string的android:tag属性。
  • 如果您既不提供前两项,系统也使用容器视图的ID。

这强烈暗示,如果在Activity.onCreated()执行setContentView(R.layout.whatever) ,并且该布局包含带有setRetainInstance(true)的片段,则在重新创build活动时,将使用其id或标记再次search。

其次,对于无UI的片段,它说

要添加没有UI的片段,请使用add(Fragment,String)(为片段提供唯一的string“tag”,而不是视图ID)从活动添加片段。 这会添加片段,但是,因为它不与活动布局中的视图关联,所以不会接收到onCreateView()的调用。 所以你不需要实现这个方法。

和文档链接到一个很好的例子 – FragmentRetainInstance.java ,我已经在下面转载为了您的方便。 它正是我所猜测的是我的问题的答案( if (...findFragmentByTag() == null) { ... )。

最后,我创build了自己的testing活动,以确切地查看哪些函数被调用。 它将输出这个,当你开始纵向和旋转到风景。 代码如下。

(这是编辑一点,以便于阅读。)

 TestActivity@415a4a30: this() TestActivity@415a4a30: onCreate() TestActivity@415a4a30: Existing fragment not found. TestFragment{41583008}: this() TestFragment{41583008} TestFragment{41583008}: onAttach(TestActivity@415a4a30) TestFragment{41583008}: onCreate() TestFragment{41583008}: onCreateView() TestFragment{41583008}: onActivityCreated() TestActivity@415a4a30: onStart() TestFragment{41583008}: onStart() TestActivity@415a4a30: onResume() TestFragment{41583008}: onResume() <rotate device> TestFragment{41583008}: onPause() TestActivity@415a4a30: onPause() TestFragment{41583008}: onStop() TestActivity@415a4a30: onStop() TestFragment{41583008}: onDestroyView() TestFragment{41583008}: onDetach() TestActivity@415a4a30: onDestroy() TestActivity@415a3380: this() TestFragment{41583008}: onAttach(TestActivity@415a3380) TestActivity@415a3380: onCreate() TestActivity@415a3380: Existing fragment found. TestFragment{41583008}: onCreateView() TestFragment{41583008}: onActivityCreated() TestActivity@415a3380: onStart() TestFragment{41583008}: onStart() TestActivity@415a3380: onResume() TestFragment{41583008}: onResume() 

请注意,Android文档是错误的:无UI的片段确实接收到对onCreateView()的调用,但可以自由返回null

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

FragmentRetainInstance.java源代码(截至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(); } } } } 

Fragment类中的onRetainCustomNonConfigurationInstance()Activity类的onRetainCustomNonConfigurationInstance()的巧妙替代,等等。

在文档中明确指出。

这里是发生了什么日志(UI片段添加需求,然后configuration更改):

默认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 - com.example.MyActivity@405196b0 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 - com.example.MyActivity@405196b0 09-29 13:23:04.881: INFO/TESTING - MYACTIVITY(4790): onStart - com.example.MyActivity@405196b0 09-29 13:23:04.881: INFO/TESTING - MYACTIVITY(4790): onResume - com.example.MyActivity@405196b0 09-29 13:23:04.891: INFO/TESTING - MYACTIVITY(4790): onAttachedToWindow - com.example.MyActivity@405196b0 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 - com.example.MyActivity@405196b0 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 - com.example.MyActivity@405196b0 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 - com.example.MyActivity@405196b0 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 - com.example.MyActivity@405196b0 09-29 13:23:15.121: INFO/TESTING - MYACTIVITY(4790): onRetainCustomNonConfigurationInstance - com.example.MyActivity@405196b0 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 - com.example.MyActivity@405196b0 09-29 13:23:15.191: INFO/TESTING - MYACTIVITY(4790): onDetachedFromWindow - com.example.MyActivity@405196b0 09-29 13:23:15.201: INFO/TESTING - MYACTIVITY(4790): Instantiated - com.example.MyActivity@4053c438 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 - com.example.MyActivity@4053c438 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 - com.example.MyActivity@4053c438 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 - com.example.MyActivity@4053c438 09-29 13:23:15.291: INFO/TESTING - MYACTIVITY(4790): onResume - com.example.MyActivity@4053c438 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 - com.example.MyActivity@4053c438 

所以,Fragment被重新创build,再次显示,这一切都是setRetainInstance(false)

现在用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 - com.example.MyActivity@4056f2e0 09-29 13:18:46.161: INFO/TESTING - MYACTIVITY(4726): onCreate - com.example.MyActivity@4056f2e0 09-29 13:18:46.161: INFO/TESTING - MYACTIVITY(4726): onStart - com.example.MyActivity@4056f2e0 09-29 13:18:46.161: INFO/TESTING - MYACTIVITY(4726): onResume - com.example.MyActivity@4056f2e0 09-29 13:18:46.191: INFO/TESTING - MYACTIVITY(4726): onAttachedToWindow - com.example.MyActivity@4056f2e0 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 - com.example.MyActivity@4056f2e0 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 - com.example.MyActivity@4056f2e0 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 - com.example.MyActivity@4056f2e0 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 - com.example.MyActivity@4056f2e0 09-29 13:19:21.961: INFO/TESTING - MYACTIVITY(4726): onRetainCustomNonConfigurationInstance - com.example.MyActivity@4056f2e0 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 - com.example.MyActivity@4056f2e0 09-29 13:19:22.111: INFO/TESTING - MYACTIVITY(4726): onDetachedFromWindow - com.example.MyActivity@4056f2e0 09-29 13:19:22.111: INFO/TESTING - MYACTIVITY(4726): Instantiated - com.example.MyActivity@4054a0e8 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 - com.example.MyActivity@4054a0e8 09-29 13:19:22.131: INFO/TESTING - MYACTIVITY(4726): onCreate - com.example.MyActivity@4054a0e8 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 - com.example.MyActivity@4054a0e8 09-29 13:19:22.141: INFO/TESTING - MYACTIVITY(4726): onResume - com.example.MyActivity@4054a0e8 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 - com.example.MyActivity@4054a0e8 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} 

注意到效果? 片段实例(对象405288c0)被保留,这是很好的。 但是保留的实例很可能拥有属于先前方向的资源,视图和对象,这可能导致内存泄漏。

在编写代码来启动这个片段的时候,必须更加小心:您必须始终检查预先存在的实例。

道德故事: setRetainInstance()最适合用于非视觉片段。