1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.app; 18 19 import android.animation.Animator; 20 import android.content.ComponentCallbacks2; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.res.Configuration; 24 import android.content.res.Resources; 25 import android.os.Bundle; 26 import android.os.Parcel; 27 import android.os.Parcelable; 28 import android.util.AndroidRuntimeException; 29 import android.util.ArrayMap; 30 import android.util.AttributeSet; 31 import android.util.DebugUtils; 32 import android.util.Log; 33 import android.util.SparseArray; 34 import android.util.SuperNotCalledException; 35 import android.view.ContextMenu; 36 import android.view.ContextMenu.ContextMenuInfo; 37 import android.view.LayoutInflater; 38 import android.view.Menu; 39 import android.view.MenuInflater; 40 import android.view.MenuItem; 41 import android.view.View; 42 import android.view.View.OnCreateContextMenuListener; 43 import android.view.ViewGroup; 44 import android.widget.AdapterView; 45 46 import java.io.FileDescriptor; 47 import java.io.PrintWriter; 48 49 final class FragmentState implements Parcelable { 50 final String mClassName; 51 final int mIndex; 52 final boolean mFromLayout; 53 final int mFragmentId; 54 final int mContainerId; 55 final String mTag; 56 final boolean mRetainInstance; 57 final boolean mDetached; 58 final Bundle mArguments; 59 60 Bundle mSavedFragmentState; 61 62 Fragment mInstance; 63 64 public FragmentState(Fragment frag) { 65 mClassName = frag.getClass().getName(); 66 mIndex = frag.mIndex; 67 mFromLayout = frag.mFromLayout; 68 mFragmentId = frag.mFragmentId; 69 mContainerId = frag.mContainerId; 70 mTag = frag.mTag; 71 mRetainInstance = frag.mRetainInstance; 72 mDetached = frag.mDetached; 73 mArguments = frag.mArguments; 74 } 75 76 public FragmentState(Parcel in) { 77 mClassName = in.readString(); 78 mIndex = in.readInt(); 79 mFromLayout = in.readInt() != 0; 80 mFragmentId = in.readInt(); 81 mContainerId = in.readInt(); 82 mTag = in.readString(); 83 mRetainInstance = in.readInt() != 0; 84 mDetached = in.readInt() != 0; 85 mArguments = in.readBundle(); 86 mSavedFragmentState = in.readBundle(); 87 } 88 89 public Fragment instantiate(Activity activity, Fragment parent) { 90 if (mInstance != null) { 91 return mInstance; 92 } 93 94 if (mArguments != null) { 95 mArguments.setClassLoader(activity.getClassLoader()); 96 } 97 98 mInstance = Fragment.instantiate(activity, mClassName, mArguments); 99 100 if (mSavedFragmentState != null) { 101 mSavedFragmentState.setClassLoader(activity.getClassLoader()); 102 mInstance.mSavedFragmentState = mSavedFragmentState; 103 } 104 mInstance.setIndex(mIndex, parent); 105 mInstance.mFromLayout = mFromLayout; 106 mInstance.mRestored = true; 107 mInstance.mFragmentId = mFragmentId; 108 mInstance.mContainerId = mContainerId; 109 mInstance.mTag = mTag; 110 mInstance.mRetainInstance = mRetainInstance; 111 mInstance.mDetached = mDetached; 112 mInstance.mFragmentManager = activity.mFragments; 113 if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG, 114 "Instantiated fragment " + mInstance); 115 116 return mInstance; 117 } 118 119 public int describeContents() { 120 return 0; 121 } 122 123 public void writeToParcel(Parcel dest, int flags) { 124 dest.writeString(mClassName); 125 dest.writeInt(mIndex); 126 dest.writeInt(mFromLayout ? 1 : 0); 127 dest.writeInt(mFragmentId); 128 dest.writeInt(mContainerId); 129 dest.writeString(mTag); 130 dest.writeInt(mRetainInstance ? 1 : 0); 131 dest.writeInt(mDetached ? 1 : 0); 132 dest.writeBundle(mArguments); 133 dest.writeBundle(mSavedFragmentState); 134 } 135 136 public static final Parcelable.Creator<FragmentState> CREATOR 137 = new Parcelable.Creator<FragmentState>() { 138 public FragmentState createFromParcel(Parcel in) { 139 return new FragmentState(in); 140 } 141 142 public FragmentState[] newArray(int size) { 143 return new FragmentState[size]; 144 } 145 }; 146 } 147 148 /** 149 * A Fragment is a piece of an application's user interface or behavior 150 * that can be placed in an {@link Activity}. Interaction with fragments 151 * is done through {@link FragmentManager}, which can be obtained via 152 * {@link Activity#getFragmentManager() Activity.getFragmentManager()} and 153 * {@link Fragment#getFragmentManager() Fragment.getFragmentManager()}. 154 * 155 * <p>The Fragment class can be used many ways to achieve a wide variety of 156 * results. In its core, it represents a particular operation or interface 157 * that is running within a larger {@link Activity}. A Fragment is closely 158 * tied to the Activity it is in, and can not be used apart from one. Though 159 * Fragment defines its own lifecycle, that lifecycle is dependent on its 160 * activity: if the activity is stopped, no fragments inside of it can be 161 * started; when the activity is destroyed, all fragments will be destroyed. 162 * 163 * <p>All subclasses of Fragment must include a public empty constructor. 164 * The framework will often re-instantiate a fragment class when needed, 165 * in particular during state restore, and needs to be able to find this 166 * constructor to instantiate it. If the empty constructor is not available, 167 * a runtime exception will occur in some cases during state restore. 168 * 169 * <p>Topics covered here: 170 * <ol> 171 * <li><a href="#OlderPlatforms">Older Platforms</a> 172 * <li><a href="#Lifecycle">Lifecycle</a> 173 * <li><a href="#Layout">Layout</a> 174 * <li><a href="#BackStack">Back Stack</a> 175 * </ol> 176 * 177 * <div class="special reference"> 178 * <h3>Developer Guides</h3> 179 * <p>For more information about using fragments, read the 180 * <a href="{@docRoot}guide/topics/fundamentals/fragments.html">Fragments</a> developer guide.</p> 181 * </div> 182 * 183 * <a name="OlderPlatforms"></a> 184 * <h3>Older Platforms</h3> 185 * 186 * While the Fragment API was introduced in 187 * {@link android.os.Build.VERSION_CODES#HONEYCOMB}, a version of the API 188 * at is also available for use on older platforms through 189 * {@link android.support.v4.app.FragmentActivity}. See the blog post 190 * <a href="http://android-developers.blogspot.com/2011/03/fragments-for-all.html"> 191 * Fragments For All</a> for more details. 192 * 193 * <a name="Lifecycle"></a> 194 * <h3>Lifecycle</h3> 195 * 196 * <p>Though a Fragment's lifecycle is tied to its owning activity, it has 197 * its own wrinkle on the standard activity lifecycle. It includes basic 198 * activity lifecycle methods such as {@link #onResume}, but also important 199 * are methods related to interactions with the activity and UI generation. 200 * 201 * <p>The core series of lifecycle methods that are called to bring a fragment 202 * up to resumed state (interacting with the user) are: 203 * 204 * <ol> 205 * <li> {@link #onAttach} called once the fragment is associated with its activity. 206 * <li> {@link #onCreate} called to do initial creation of the fragment. 207 * <li> {@link #onCreateView} creates and returns the view hierarchy associated 208 * with the fragment. 209 * <li> {@link #onActivityCreated} tells the fragment that its activity has 210 * completed its own {@link Activity#onCreate Activity.onCreate()}. 211 * <li> {@link #onViewStateRestored} tells the fragment that all of the saved 212 * state of its view hierarchy has been restored. 213 * <li> {@link #onStart} makes the fragment visible to the user (based on its 214 * containing activity being started). 215 * <li> {@link #onResume} makes the fragment interacting with the user (based on its 216 * containing activity being resumed). 217 * </ol> 218 * 219 * <p>As a fragment is no longer being used, it goes through a reverse 220 * series of callbacks: 221 * 222 * <ol> 223 * <li> {@link #onPause} fragment is no longer interacting with the user either 224 * because its activity is being paused or a fragment operation is modifying it 225 * in the activity. 226 * <li> {@link #onStop} fragment is no longer visible to the user either 227 * because its activity is being stopped or a fragment operation is modifying it 228 * in the activity. 229 * <li> {@link #onDestroyView} allows the fragment to clean up resources 230 * associated with its View. 231 * <li> {@link #onDestroy} called to do final cleanup of the fragment's state. 232 * <li> {@link #onDetach} called immediately prior to the fragment no longer 233 * being associated with its activity. 234 * </ol> 235 * 236 * <a name="Layout"></a> 237 * <h3>Layout</h3> 238 * 239 * <p>Fragments can be used as part of your application's layout, allowing 240 * you to better modularize your code and more easily adjust your user 241 * interface to the screen it is running on. As an example, we can look 242 * at a simple program consisting of a list of items, and display of the 243 * details of each item.</p> 244 * 245 * <p>An activity's layout XML can include <code><fragment></code> tags 246 * to embed fragment instances inside of the layout. For example, here is 247 * a simple layout that embeds one fragment:</p> 248 * 249 * {@sample development/samples/ApiDemos/res/layout/fragment_layout.xml layout} 250 * 251 * <p>The layout is installed in the activity in the normal way:</p> 252 * 253 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java 254 * main} 255 * 256 * <p>The titles fragment, showing a list of titles, is fairly simple, relying 257 * on {@link ListFragment} for most of its work. Note the implementation of 258 * clicking an item: depending on the current activity's layout, it can either 259 * create and display a new fragment to show the details in-place (more about 260 * this later), or start a new activity to show the details.</p> 261 * 262 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java 263 * titles} 264 * 265 * <p>The details fragment showing the contents of a selected item just 266 * displays a string of text based on an index of a string array built in to 267 * the app:</p> 268 * 269 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java 270 * details} 271 * 272 * <p>In this case when the user clicks on a title, there is no details 273 * container in the current activity, so the titles fragment's click code will 274 * launch a new activity to display the details fragment:</p> 275 * 276 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java 277 * details_activity} 278 * 279 * <p>However the screen may be large enough to show both the list of titles 280 * and details about the currently selected title. To use such a layout on 281 * a landscape screen, this alternative layout can be placed under layout-land:</p> 282 * 283 * {@sample development/samples/ApiDemos/res/layout-land/fragment_layout.xml layout} 284 * 285 * <p>Note how the prior code will adjust to this alternative UI flow: the titles 286 * fragment will now embed the details fragment inside of this activity, and the 287 * details activity will finish itself if it is running in a configuration 288 * where the details can be shown in-place. 289 * 290 * <p>When a configuration change causes the activity hosting these fragments 291 * to restart, its new instance may use a different layout that doesn't 292 * include the same fragments as the previous layout. In this case all of 293 * the previous fragments will still be instantiated and running in the new 294 * instance. However, any that are no longer associated with a <fragment> 295 * tag in the view hierarchy will not have their content view created 296 * and will return false from {@link #isInLayout}. (The code here also shows 297 * how you can determine if a fragment placed in a container is no longer 298 * running in a layout with that container and avoid creating its view hierarchy 299 * in that case.) 300 * 301 * <p>The attributes of the <fragment> tag are used to control the 302 * LayoutParams provided when attaching the fragment's view to the parent 303 * container. They can also be parsed by the fragment in {@link #onInflate} 304 * as parameters. 305 * 306 * <p>The fragment being instantiated must have some kind of unique identifier 307 * so that it can be re-associated with a previous instance if the parent 308 * activity needs to be destroyed and recreated. This can be provided these 309 * ways: 310 * 311 * <ul> 312 * <li>If nothing is explicitly supplied, the view ID of the container will 313 * be used. 314 * <li><code>android:tag</code> can be used in <fragment> to provide 315 * a specific tag name for the fragment. 316 * <li><code>android:id</code> can be used in <fragment> to provide 317 * a specific identifier for the fragment. 318 * </ul> 319 * 320 * <a name="BackStack"></a> 321 * <h3>Back Stack</h3> 322 * 323 * <p>The transaction in which fragments are modified can be placed on an 324 * internal back-stack of the owning activity. When the user presses back 325 * in the activity, any transactions on the back stack are popped off before 326 * the activity itself is finished. 327 * 328 * <p>For example, consider this simple fragment that is instantiated with 329 * an integer argument and displays that in a TextView in its UI:</p> 330 * 331 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentStack.java 332 * fragment} 333 * 334 * <p>A function that creates a new instance of the fragment, replacing 335 * whatever current fragment instance is being shown and pushing that change 336 * on to the back stack could be written as: 337 * 338 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentStack.java 339 * add_stack} 340 * 341 * <p>After each call to this function, a new entry is on the stack, and 342 * pressing back will pop it to return the user to whatever previous state 343 * the activity UI was in. 344 */ 345 public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListener { 346 private static final ArrayMap<String, Class<?>> sClassMap = 347 new ArrayMap<String, Class<?>>(); 348 349 static final int INVALID_STATE = -1; // Invalid state used as a null value. 350 static final int INITIALIZING = 0; // Not yet created. 351 static final int CREATED = 1; // Created. 352 static final int ACTIVITY_CREATED = 2; // The activity has finished its creation. 353 static final int STOPPED = 3; // Fully created, not started. 354 static final int STARTED = 4; // Created and started, not resumed. 355 static final int RESUMED = 5; // Created started and resumed. 356 357 int mState = INITIALIZING; 358 359 // Non-null if the fragment's view hierarchy is currently animating away, 360 // meaning we need to wait a bit on completely destroying it. This is the 361 // animation that is running. 362 Animator mAnimatingAway; 363 364 // If mAnimatingAway != null, this is the state we should move to once the 365 // animation is done. 366 int mStateAfterAnimating; 367 368 // When instantiated from saved state, this is the saved state. 369 Bundle mSavedFragmentState; 370 SparseArray<Parcelable> mSavedViewState; 371 372 // Index into active fragment array. 373 int mIndex = -1; 374 375 // Internal unique name for this fragment; 376 String mWho; 377 378 // Construction arguments; 379 Bundle mArguments; 380 381 // Target fragment. 382 Fragment mTarget; 383 384 // For use when retaining a fragment: this is the index of the last mTarget. 385 int mTargetIndex = -1; 386 387 // Target request code. 388 int mTargetRequestCode; 389 390 // True if the fragment is in the list of added fragments. 391 boolean mAdded; 392 393 // If set this fragment is being removed from its activity. 394 boolean mRemoving; 395 396 // True if the fragment is in the resumed state. 397 boolean mResumed; 398 399 // Set to true if this fragment was instantiated from a layout file. 400 boolean mFromLayout; 401 402 // Set to true when the view has actually been inflated in its layout. 403 boolean mInLayout; 404 405 // True if this fragment has been restored from previously saved state. 406 boolean mRestored; 407 408 // Number of active back stack entries this fragment is in. 409 int mBackStackNesting; 410 411 // The fragment manager we are associated with. Set as soon as the 412 // fragment is used in a transaction; cleared after it has been removed 413 // from all transactions. 414 FragmentManagerImpl mFragmentManager; 415 416 // Activity this fragment is attached to. 417 Activity mActivity; 418 419 // Private fragment manager for child fragments inside of this one. 420 FragmentManagerImpl mChildFragmentManager; 421 422 // If this Fragment is contained in another Fragment, this is that container. 423 Fragment mParentFragment; 424 425 // The optional identifier for this fragment -- either the container ID if it 426 // was dynamically added to the view hierarchy, or the ID supplied in 427 // layout. 428 int mFragmentId; 429 430 // When a fragment is being dynamically added to the view hierarchy, this 431 // is the identifier of the parent container it is being added to. 432 int mContainerId; 433 434 // The optional named tag for this fragment -- usually used to find 435 // fragments that are not part of the layout. 436 String mTag; 437 438 // Set to true when the app has requested that this fragment be hidden 439 // from the user. 440 boolean mHidden; 441 442 // Set to true when the app has requested that this fragment be detached. 443 boolean mDetached; 444 445 // If set this fragment would like its instance retained across 446 // configuration changes. 447 boolean mRetainInstance; 448 449 // If set this fragment is being retained across the current config change. 450 boolean mRetaining; 451 452 // If set this fragment has menu items to contribute. 453 boolean mHasMenu; 454 455 // Set to true to allow the fragment's menu to be shown. 456 boolean mMenuVisible = true; 457 458 // Used to verify that subclasses call through to super class. 459 boolean mCalled; 460 461 // If app has requested a specific animation, this is the one to use. 462 int mNextAnim; 463 464 // The parent container of the fragment after dynamically added to UI. 465 ViewGroup mContainer; 466 467 // The View generated for this fragment. 468 View mView; 469 470 // Whether this fragment should defer starting until after other fragments 471 // have been started and their loaders are finished. 472 boolean mDeferStart; 473 474 // Hint provided by the app that this fragment is currently visible to the user. 475 boolean mUserVisibleHint = true; 476 477 LoaderManagerImpl mLoaderManager; 478 boolean mLoadersStarted; 479 boolean mCheckedForLoaderManager; 480 481 /** 482 * State information that has been retrieved from a fragment instance 483 * through {@link FragmentManager#saveFragmentInstanceState(Fragment) 484 * FragmentManager.saveFragmentInstanceState}. 485 */ 486 public static class SavedState implements Parcelable { 487 final Bundle mState; 488 489 SavedState(Bundle state) { 490 mState = state; 491 } 492 493 SavedState(Parcel in, ClassLoader loader) { 494 mState = in.readBundle(); 495 if (loader != null && mState != null) { 496 mState.setClassLoader(loader); 497 } 498 } 499 500 @Override 501 public int describeContents() { 502 return 0; 503 } 504 505 @Override 506 public void writeToParcel(Parcel dest, int flags) { 507 dest.writeBundle(mState); 508 } 509 510 public static final Parcelable.ClassLoaderCreator<SavedState> CREATOR 511 = new Parcelable.ClassLoaderCreator<SavedState>() { 512 public SavedState createFromParcel(Parcel in) { 513 return new SavedState(in, null); 514 } 515 516 public SavedState createFromParcel(Parcel in, ClassLoader loader) { 517 return new SavedState(in, loader); 518 } 519 520 public SavedState[] newArray(int size) { 521 return new SavedState[size]; 522 } 523 }; 524 } 525 526 /** 527 * Thrown by {@link Fragment#instantiate(Context, String, Bundle)} when 528 * there is an instantiation failure. 529 */ 530 static public class InstantiationException extends AndroidRuntimeException { 531 public InstantiationException(String msg, Exception cause) { 532 super(msg, cause); 533 } 534 } 535 536 /** 537 * Default constructor. <strong>Every</strong> fragment must have an 538 * empty constructor, so it can be instantiated when restoring its 539 * activity's state. It is strongly recommended that subclasses do not 540 * have other constructors with parameters, since these constructors 541 * will not be called when the fragment is re-instantiated; instead, 542 * arguments can be supplied by the caller with {@link #setArguments} 543 * and later retrieved by the Fragment with {@link #getArguments}. 544 * 545 * <p>Applications should generally not implement a constructor. The 546 * first place application code an run where the fragment is ready to 547 * be used is in {@link #onAttach(Activity)}, the point where the fragment 548 * is actually associated with its activity. Some applications may also 549 * want to implement {@link #onInflate} to retrieve attributes from a 550 * layout resource, though should take care here because this happens for 551 * the fragment is attached to its activity. 552 */ 553 public Fragment() { 554 } 555 556 /** 557 * Like {@link #instantiate(Context, String, Bundle)} but with a null 558 * argument Bundle. 559 */ 560 public static Fragment instantiate(Context context, String fname) { 561 return instantiate(context, fname, null); 562 } 563 564 /** 565 * Create a new instance of a Fragment with the given class name. This is 566 * the same as calling its empty constructor. 567 * 568 * @param context The calling context being used to instantiate the fragment. 569 * This is currently just used to get its ClassLoader. 570 * @param fname The class name of the fragment to instantiate. 571 * @param args Bundle of arguments to supply to the fragment, which it 572 * can retrieve with {@link #getArguments()}. May be null. 573 * @return Returns a new fragment instance. 574 * @throws InstantiationException If there is a failure in instantiating 575 * the given fragment class. This is a runtime exception; it is not 576 * normally expected to happen. 577 */ 578 public static Fragment instantiate(Context context, String fname, Bundle args) { 579 try { 580 Class<?> clazz = sClassMap.get(fname); 581 if (clazz == null) { 582 // Class not found in the cache, see if it's real, and try to add it 583 clazz = context.getClassLoader().loadClass(fname); 584 if (!Fragment.class.isAssignableFrom(clazz)) { 585 throw new InstantiationException("Trying to instantiate a class " + fname 586 + " that is not a Fragment", new ClassCastException()); 587 } 588 sClassMap.put(fname, clazz); 589 } 590 Fragment f = (Fragment)clazz.newInstance(); 591 if (args != null) { 592 args.setClassLoader(f.getClass().getClassLoader()); 593 f.mArguments = args; 594 } 595 return f; 596 } catch (ClassNotFoundException e) { 597 throw new InstantiationException("Unable to instantiate fragment " + fname 598 + ": make sure class name exists, is public, and has an" 599 + " empty constructor that is public", e); 600 } catch (java.lang.InstantiationException e) { 601 throw new InstantiationException("Unable to instantiate fragment " + fname 602 + ": make sure class name exists, is public, and has an" 603 + " empty constructor that is public", e); 604 } catch (IllegalAccessException e) { 605 throw new InstantiationException("Unable to instantiate fragment " + fname 606 + ": make sure class name exists, is public, and has an" 607 + " empty constructor that is public", e); 608 } 609 } 610 611 final void restoreViewState(Bundle savedInstanceState) { 612 if (mSavedViewState != null) { 613 mView.restoreHierarchyState(mSavedViewState); 614 mSavedViewState = null; 615 } 616 mCalled = false; 617 onViewStateRestored(savedInstanceState); 618 if (!mCalled) { 619 throw new SuperNotCalledException("Fragment " + this 620 + " did not call through to super.onViewStateRestored()"); 621 } 622 } 623 624 final void setIndex(int index, Fragment parent) { 625 mIndex = index; 626 if (parent != null) { 627 mWho = parent.mWho + ":" + mIndex; 628 } else { 629 mWho = "android:fragment:" + mIndex; 630 } 631 } 632 633 final boolean isInBackStack() { 634 return mBackStackNesting > 0; 635 } 636 637 /** 638 * Subclasses can not override equals(). 639 */ 640 @Override final public boolean equals(Object o) { 641 return super.equals(o); 642 } 643 644 /** 645 * Subclasses can not override hashCode(). 646 */ 647 @Override final public int hashCode() { 648 return super.hashCode(); 649 } 650 651 @Override 652 public String toString() { 653 StringBuilder sb = new StringBuilder(128); 654 DebugUtils.buildShortClassTag(this, sb); 655 if (mIndex >= 0) { 656 sb.append(" #"); 657 sb.append(mIndex); 658 } 659 if (mFragmentId != 0) { 660 sb.append(" id=0x"); 661 sb.append(Integer.toHexString(mFragmentId)); 662 } 663 if (mTag != null) { 664 sb.append(" "); 665 sb.append(mTag); 666 } 667 sb.append('}'); 668 return sb.toString(); 669 } 670 671 /** 672 * Return the identifier this fragment is known by. This is either 673 * the android:id value supplied in a layout or the container view ID 674 * supplied when adding the fragment. 675 */ 676 final public int getId() { 677 return mFragmentId; 678 } 679 680 /** 681 * Get the tag name of the fragment, if specified. 682 */ 683 final public String getTag() { 684 return mTag; 685 } 686 687 /** 688 * Supply the construction arguments for this fragment. This can only 689 * be called before the fragment has been attached to its activity; that 690 * is, you should call it immediately after constructing the fragment. The 691 * arguments supplied here will be retained across fragment destroy and 692 * creation. 693 */ 694 public void setArguments(Bundle args) { 695 if (mIndex >= 0) { 696 throw new IllegalStateException("Fragment already active"); 697 } 698 mArguments = args; 699 } 700 701 /** 702 * Return the arguments supplied when the fragment was instantiated, 703 * if any. 704 */ 705 final public Bundle getArguments() { 706 return mArguments; 707 } 708 709 /** 710 * Set the initial saved state that this Fragment should restore itself 711 * from when first being constructed, as returned by 712 * {@link FragmentManager#saveFragmentInstanceState(Fragment) 713 * FragmentManager.saveFragmentInstanceState}. 714 * 715 * @param state The state the fragment should be restored from. 716 */ 717 public void setInitialSavedState(SavedState state) { 718 if (mIndex >= 0) { 719 throw new IllegalStateException("Fragment already active"); 720 } 721 mSavedFragmentState = state != null && state.mState != null 722 ? state.mState : null; 723 } 724 725 /** 726 * Optional target for this fragment. This may be used, for example, 727 * if this fragment is being started by another, and when done wants to 728 * give a result back to the first. The target set here is retained 729 * across instances via {@link FragmentManager#putFragment 730 * FragmentManager.putFragment()}. 731 * 732 * @param fragment The fragment that is the target of this one. 733 * @param requestCode Optional request code, for convenience if you 734 * are going to call back with {@link #onActivityResult(int, int, Intent)}. 735 */ 736 public void setTargetFragment(Fragment fragment, int requestCode) { 737 mTarget = fragment; 738 mTargetRequestCode = requestCode; 739 } 740 741 /** 742 * Return the target fragment set by {@link #setTargetFragment}. 743 */ 744 final public Fragment getTargetFragment() { 745 return mTarget; 746 } 747 748 /** 749 * Return the target request code set by {@link #setTargetFragment}. 750 */ 751 final public int getTargetRequestCode() { 752 return mTargetRequestCode; 753 } 754 755 /** 756 * Return the Activity this fragment is currently associated with. 757 */ 758 final public Activity getActivity() { 759 return mActivity; 760 } 761 762 /** 763 * Return <code>getActivity().getResources()</code>. 764 */ 765 final public Resources getResources() { 766 if (mActivity == null) { 767 throw new IllegalStateException("Fragment " + this + " not attached to Activity"); 768 } 769 return mActivity.getResources(); 770 } 771 772 /** 773 * Return a localized, styled CharSequence from the application's package's 774 * default string table. 775 * 776 * @param resId Resource id for the CharSequence text 777 */ 778 public final CharSequence getText(int resId) { 779 return getResources().getText(resId); 780 } 781 782 /** 783 * Return a localized string from the application's package's 784 * default string table. 785 * 786 * @param resId Resource id for the string 787 */ 788 public final String getString(int resId) { 789 return getResources().getString(resId); 790 } 791 792 /** 793 * Return a localized formatted string from the application's package's 794 * default string table, substituting the format arguments as defined in 795 * {@link java.util.Formatter} and {@link java.lang.String#format}. 796 * 797 * @param resId Resource id for the format string 798 * @param formatArgs The format arguments that will be used for substitution. 799 */ 800 801 public final String getString(int resId, Object... formatArgs) { 802 return getResources().getString(resId, formatArgs); 803 } 804 805 /** 806 * Return the FragmentManager for interacting with fragments associated 807 * with this fragment's activity. Note that this will be non-null slightly 808 * before {@link #getActivity()}, during the time from when the fragment is 809 * placed in a {@link FragmentTransaction} until it is committed and 810 * attached to its activity. 811 * 812 * <p>If this Fragment is a child of another Fragment, the FragmentManager 813 * returned here will be the parent's {@link #getChildFragmentManager()}. 814 */ 815 final public FragmentManager getFragmentManager() { 816 return mFragmentManager; 817 } 818 819 /** 820 * Return a private FragmentManager for placing and managing Fragments 821 * inside of this Fragment. 822 */ 823 final public FragmentManager getChildFragmentManager() { 824 if (mChildFragmentManager == null) { 825 instantiateChildFragmentManager(); 826 if (mState >= RESUMED) { 827 mChildFragmentManager.dispatchResume(); 828 } else if (mState >= STARTED) { 829 mChildFragmentManager.dispatchStart(); 830 } else if (mState >= ACTIVITY_CREATED) { 831 mChildFragmentManager.dispatchActivityCreated(); 832 } else if (mState >= CREATED) { 833 mChildFragmentManager.dispatchCreate(); 834 } 835 } 836 return mChildFragmentManager; 837 } 838 839 /** 840 * Returns the parent Fragment containing this Fragment. If this Fragment 841 * is attached directly to an Activity, returns null. 842 */ 843 final public Fragment getParentFragment() { 844 return mParentFragment; 845 } 846 847 /** 848 * Return true if the fragment is currently added to its activity. 849 */ 850 final public boolean isAdded() { 851 return mActivity != null && mAdded; 852 } 853 854 /** 855 * Return true if the fragment has been explicitly detached from the UI. 856 * That is, {@link FragmentTransaction#detach(Fragment) 857 * FragmentTransaction.detach(Fragment)} has been used on it. 858 */ 859 final public boolean isDetached() { 860 return mDetached; 861 } 862 863 /** 864 * Return true if this fragment is currently being removed from its 865 * activity. This is <em>not</em> whether its activity is finishing, but 866 * rather whether it is in the process of being removed from its activity. 867 */ 868 final public boolean isRemoving() { 869 return mRemoving; 870 } 871 872 /** 873 * Return true if the layout is included as part of an activity view 874 * hierarchy via the <fragment> tag. This will always be true when 875 * fragments are created through the <fragment> tag, <em>except</em> 876 * in the case where an old fragment is restored from a previous state and 877 * it does not appear in the layout of the current state. 878 */ 879 final public boolean isInLayout() { 880 return mInLayout; 881 } 882 883 /** 884 * Return true if the fragment is in the resumed state. This is true 885 * for the duration of {@link #onResume()} and {@link #onPause()} as well. 886 */ 887 final public boolean isResumed() { 888 return mResumed; 889 } 890 891 /** 892 * Return true if the fragment is currently visible to the user. This means 893 * it: (1) has been added, (2) has its view attached to the window, and 894 * (3) is not hidden. 895 */ 896 final public boolean isVisible() { 897 return isAdded() && !isHidden() && mView != null 898 && mView.getWindowToken() != null && mView.getVisibility() == View.VISIBLE; 899 } 900 901 /** 902 * Return true if the fragment has been hidden. By default fragments 903 * are shown. You can find out about changes to this state with 904 * {@link #onHiddenChanged}. Note that the hidden state is orthogonal 905 * to other states -- that is, to be visible to the user, a fragment 906 * must be both started and not hidden. 907 */ 908 final public boolean isHidden() { 909 return mHidden; 910 } 911 912 /** 913 * Called when the hidden state (as returned by {@link #isHidden()} of 914 * the fragment has changed. Fragments start out not hidden; this will 915 * be called whenever the fragment changes state from that. 916 * @param hidden True if the fragment is now hidden, false if it is not 917 * visible. 918 */ 919 public void onHiddenChanged(boolean hidden) { 920 } 921 922 /** 923 * Control whether a fragment instance is retained across Activity 924 * re-creation (such as from a configuration change). This can only 925 * be used with fragments not in the back stack. If set, the fragment 926 * lifecycle will be slightly different when an activity is recreated: 927 * <ul> 928 * <li> {@link #onDestroy()} will not be called (but {@link #onDetach()} still 929 * will be, because the fragment is being detached from its current activity). 930 * <li> {@link #onCreate(Bundle)} will not be called since the fragment 931 * is not being re-created. 932 * <li> {@link #onAttach(Activity)} and {@link #onActivityCreated(Bundle)} <b>will</b> 933 * still be called. 934 * </ul> 935 */ 936 public void setRetainInstance(boolean retain) { 937 if (retain && mParentFragment != null) { 938 throw new IllegalStateException( 939 "Can't retain fragements that are nested in other fragments"); 940 } 941 mRetainInstance = retain; 942 } 943 944 final public boolean getRetainInstance() { 945 return mRetainInstance; 946 } 947 948 /** 949 * Report that this fragment would like to participate in populating 950 * the options menu by receiving a call to {@link #onCreateOptionsMenu} 951 * and related methods. 952 * 953 * @param hasMenu If true, the fragment has menu items to contribute. 954 */ 955 public void setHasOptionsMenu(boolean hasMenu) { 956 if (mHasMenu != hasMenu) { 957 mHasMenu = hasMenu; 958 if (isAdded() && !isHidden()) { 959 mFragmentManager.invalidateOptionsMenu(); 960 } 961 } 962 } 963 964 /** 965 * Set a hint for whether this fragment's menu should be visible. This 966 * is useful if you know that a fragment has been placed in your view 967 * hierarchy so that the user can not currently seen it, so any menu items 968 * it has should also not be shown. 969 * 970 * @param menuVisible The default is true, meaning the fragment's menu will 971 * be shown as usual. If false, the user will not see the menu. 972 */ 973 public void setMenuVisibility(boolean menuVisible) { 974 if (mMenuVisible != menuVisible) { 975 mMenuVisible = menuVisible; 976 if (mHasMenu && isAdded() && !isHidden()) { 977 mFragmentManager.invalidateOptionsMenu(); 978 } 979 } 980 } 981 982 /** 983 * Set a hint to the system about whether this fragment's UI is currently visible 984 * to the user. This hint defaults to true and is persistent across fragment instance 985 * state save and restore. 986 * 987 * <p>An app may set this to false to indicate that the fragment's UI is 988 * scrolled out of visibility or is otherwise not directly visible to the user. 989 * This may be used by the system to prioritize operations such as fragment lifecycle updates 990 * or loader ordering behavior.</p> 991 * 992 * @param isVisibleToUser true if this fragment's UI is currently visible to the user (default), 993 * false if it is not. 994 */ 995 public void setUserVisibleHint(boolean isVisibleToUser) { 996 if (!mUserVisibleHint && isVisibleToUser && mState < STARTED) { 997 mFragmentManager.performPendingDeferredStart(this); 998 } 999 mUserVisibleHint = isVisibleToUser; 1000 mDeferStart = !isVisibleToUser; 1001 } 1002 1003 /** 1004 * @return The current value of the user-visible hint on this fragment. 1005 * @see #setUserVisibleHint(boolean) 1006 */ 1007 public boolean getUserVisibleHint() { 1008 return mUserVisibleHint; 1009 } 1010 1011 /** 1012 * Return the LoaderManager for this fragment, creating it if needed. 1013 */ 1014 public LoaderManager getLoaderManager() { 1015 if (mLoaderManager != null) { 1016 return mLoaderManager; 1017 } 1018 if (mActivity == null) { 1019 throw new IllegalStateException("Fragment " + this + " not attached to Activity"); 1020 } 1021 mCheckedForLoaderManager = true; 1022 mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, true); 1023 return mLoaderManager; 1024 } 1025 1026 /** 1027 * Call {@link Activity#startActivity(Intent)} from the fragment's 1028 * containing Activity. 1029 * 1030 * @param intent The intent to start. 1031 */ 1032 public void startActivity(Intent intent) { 1033 startActivity(intent, null); 1034 } 1035 1036 /** 1037 * Call {@link Activity#startActivity(Intent, Bundle)} from the fragment's 1038 * containing Activity. 1039 * 1040 * @param intent The intent to start. 1041 * @param options Additional options for how the Activity should be started. 1042 * See {@link android.content.Context#startActivity(Intent, Bundle) 1043 * Context.startActivity(Intent, Bundle)} for more details. 1044 */ 1045 public void startActivity(Intent intent, Bundle options) { 1046 if (mActivity == null) { 1047 throw new IllegalStateException("Fragment " + this + " not attached to Activity"); 1048 } 1049 if (options != null) { 1050 mActivity.startActivityFromFragment(this, intent, -1, options); 1051 } else { 1052 // Note we want to go through this call for compatibility with 1053 // applications that may have overridden the method. 1054 mActivity.startActivityFromFragment(this, intent, -1); 1055 } 1056 } 1057 1058 /** 1059 * Call {@link Activity#startActivityForResult(Intent, int)} from the fragment's 1060 * containing Activity. 1061 */ 1062 public void startActivityForResult(Intent intent, int requestCode) { 1063 startActivityForResult(intent, requestCode, null); 1064 } 1065 1066 /** 1067 * Call {@link Activity#startActivityForResult(Intent, int, Bundle)} from the fragment's 1068 * containing Activity. 1069 */ 1070 public void startActivityForResult(Intent intent, int requestCode, Bundle options) { 1071 if (mActivity == null) { 1072 throw new IllegalStateException("Fragment " + this + " not attached to Activity"); 1073 } 1074 if (options != null) { 1075 mActivity.startActivityFromFragment(this, intent, requestCode, options); 1076 } else { 1077 // Note we want to go through this call for compatibility with 1078 // applications that may have overridden the method. 1079 mActivity.startActivityFromFragment(this, intent, requestCode, options); 1080 } 1081 } 1082 1083 /** 1084 * Receive the result from a previous call to 1085 * {@link #startActivityForResult(Intent, int)}. This follows the 1086 * related Activity API as described there in 1087 * {@link Activity#onActivityResult(int, int, Intent)}. 1088 * 1089 * @param requestCode The integer request code originally supplied to 1090 * startActivityForResult(), allowing you to identify who this 1091 * result came from. 1092 * @param resultCode The integer result code returned by the child activity 1093 * through its setResult(). 1094 * @param data An Intent, which can return result data to the caller 1095 * (various data can be attached to Intent "extras"). 1096 */ 1097 public void onActivityResult(int requestCode, int resultCode, Intent data) { 1098 } 1099 1100 /** 1101 * @hide Hack so that DialogFragment can make its Dialog before creating 1102 * its views, and the view construction can use the dialog's context for 1103 * inflation. Maybe this should become a public API. Note sure. 1104 */ 1105 public LayoutInflater getLayoutInflater(Bundle savedInstanceState) { 1106 return mActivity.getLayoutInflater(); 1107 } 1108 1109 /** 1110 * @deprecated Use {@link #onInflate(Activity, AttributeSet, Bundle)} instead. 1111 */ 1112 @Deprecated 1113 public void onInflate(AttributeSet attrs, Bundle savedInstanceState) { 1114 mCalled = true; 1115 } 1116 1117 /** 1118 * Called when a fragment is being created as part of a view layout 1119 * inflation, typically from setting the content view of an activity. This 1120 * may be called immediately after the fragment is created from a <fragment> 1121 * tag in a layout file. Note this is <em>before</em> the fragment's 1122 * {@link #onAttach(Activity)} has been called; all you should do here is 1123 * parse the attributes and save them away. 1124 * 1125 * <p>This is called every time the fragment is inflated, even if it is 1126 * being inflated into a new instance with saved state. It typically makes 1127 * sense to re-parse the parameters each time, to allow them to change with 1128 * different configurations.</p> 1129 * 1130 * <p>Here is a typical implementation of a fragment that can take parameters 1131 * both through attributes supplied here as well from {@link #getArguments()}:</p> 1132 * 1133 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentArguments.java 1134 * fragment} 1135 * 1136 * <p>Note that parsing the XML attributes uses a "styleable" resource. The 1137 * declaration for the styleable used here is:</p> 1138 * 1139 * {@sample development/samples/ApiDemos/res/values/attrs.xml fragment_arguments} 1140 * 1141 * <p>The fragment can then be declared within its activity's content layout 1142 * through a tag like this:</p> 1143 * 1144 * {@sample development/samples/ApiDemos/res/layout/fragment_arguments.xml from_attributes} 1145 * 1146 * <p>This fragment can also be created dynamically from arguments given 1147 * at runtime in the arguments Bundle; here is an example of doing so at 1148 * creation of the containing activity:</p> 1149 * 1150 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentArguments.java 1151 * create} 1152 * 1153 * @param activity The Activity that is inflating this fragment. 1154 * @param attrs The attributes at the tag where the fragment is 1155 * being created. 1156 * @param savedInstanceState If the fragment is being re-created from 1157 * a previous saved state, this is the state. 1158 */ 1159 public void onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState) { 1160 onInflate(attrs, savedInstanceState); 1161 mCalled = true; 1162 } 1163 1164 /** 1165 * Called when a fragment is first attached to its activity. 1166 * {@link #onCreate(Bundle)} will be called after this. 1167 */ 1168 public void onAttach(Activity activity) { 1169 mCalled = true; 1170 } 1171 1172 /** 1173 * Called when a fragment loads an animation. 1174 */ 1175 public Animator onCreateAnimator(int transit, boolean enter, int nextAnim) { 1176 return null; 1177 } 1178 1179 /** 1180 * Called to do initial creation of a fragment. This is called after 1181 * {@link #onAttach(Activity)} and before 1182 * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}. 1183 * 1184 * <p>Note that this can be called while the fragment's activity is 1185 * still in the process of being created. As such, you can not rely 1186 * on things like the activity's content view hierarchy being initialized 1187 * at this point. If you want to do work once the activity itself is 1188 * created, see {@link #onActivityCreated(Bundle)}. 1189 * 1190 * @param savedInstanceState If the fragment is being re-created from 1191 * a previous saved state, this is the state. 1192 */ 1193 public void onCreate(Bundle savedInstanceState) { 1194 mCalled = true; 1195 } 1196 1197 /** 1198 * Called to have the fragment instantiate its user interface view. 1199 * This is optional, and non-graphical fragments can return null (which 1200 * is the default implementation). This will be called between 1201 * {@link #onCreate(Bundle)} and {@link #onActivityCreated(Bundle)}. 1202 * 1203 * <p>If you return a View from here, you will later be called in 1204 * {@link #onDestroyView} when the view is being released. 1205 * 1206 * @param inflater The LayoutInflater object that can be used to inflate 1207 * any views in the fragment, 1208 * @param container If non-null, this is the parent view that the fragment's 1209 * UI should be attached to. The fragment should not add the view itself, 1210 * but this can be used to generate the LayoutParams of the view. 1211 * @param savedInstanceState If non-null, this fragment is being re-constructed 1212 * from a previous saved state as given here. 1213 * 1214 * @return Return the View for the fragment's UI, or null. 1215 */ 1216 public View onCreateView(LayoutInflater inflater, ViewGroup container, 1217 Bundle savedInstanceState) { 1218 return null; 1219 } 1220 1221 /** 1222 * Called immediately after {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)} 1223 * has returned, but before any saved state has been restored in to the view. 1224 * This gives subclasses a chance to initialize themselves once 1225 * they know their view hierarchy has been completely created. The fragment's 1226 * view hierarchy is not however attached to its parent at this point. 1227 * @param view The View returned by {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}. 1228 * @param savedInstanceState If non-null, this fragment is being re-constructed 1229 * from a previous saved state as given here. 1230 */ 1231 public void onViewCreated(View view, Bundle savedInstanceState) { 1232 } 1233 1234 /** 1235 * Get the root view for the fragment's layout (the one returned by {@link #onCreateView}), 1236 * if provided. 1237 * 1238 * @return The fragment's root view, or null if it has no layout. 1239 */ 1240 public View getView() { 1241 return mView; 1242 } 1243 1244 /** 1245 * Called when the fragment's activity has been created and this 1246 * fragment's view hierarchy instantiated. It can be used to do final 1247 * initialization once these pieces are in place, such as retrieving 1248 * views or restoring state. It is also useful for fragments that use 1249 * {@link #setRetainInstance(boolean)} to retain their instance, 1250 * as this callback tells the fragment when it is fully associated with 1251 * the new activity instance. This is called after {@link #onCreateView} 1252 * and before {@link #onViewStateRestored(Bundle)}. 1253 * 1254 * @param savedInstanceState If the fragment is being re-created from 1255 * a previous saved state, this is the state. 1256 */ 1257 public void onActivityCreated(Bundle savedInstanceState) { 1258 mCalled = true; 1259 } 1260 1261 /** 1262 * Called when all saved state has been restored into the view hierarchy 1263 * of the fragment. This can be used to do initialization based on saved 1264 * state that you are letting the view hierarchy track itself, such as 1265 * whether check box widgets are currently checked. This is called 1266 * after {@link #onActivityCreated(Bundle)} and before 1267 * {@link #onStart()}. 1268 * 1269 * @param savedInstanceState If the fragment is being re-created from 1270 * a previous saved state, this is the state. 1271 */ 1272 public void onViewStateRestored(Bundle savedInstanceState) { 1273 mCalled = true; 1274 } 1275 1276 /** 1277 * Called when the Fragment is visible to the user. This is generally 1278 * tied to {@link Activity#onStart() Activity.onStart} of the containing 1279 * Activity's lifecycle. 1280 */ 1281 public void onStart() { 1282 mCalled = true; 1283 1284 if (!mLoadersStarted) { 1285 mLoadersStarted = true; 1286 if (!mCheckedForLoaderManager) { 1287 mCheckedForLoaderManager = true; 1288 mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, false); 1289 } 1290 if (mLoaderManager != null) { 1291 mLoaderManager.doStart(); 1292 } 1293 } 1294 } 1295 1296 /** 1297 * Called when the fragment is visible to the user and actively running. 1298 * This is generally 1299 * tied to {@link Activity#onResume() Activity.onResume} of the containing 1300 * Activity's lifecycle. 1301 */ 1302 public void onResume() { 1303 mCalled = true; 1304 } 1305 1306 /** 1307 * Called to ask the fragment to save its current dynamic state, so it 1308 * can later be reconstructed in a new instance of its process is 1309 * restarted. If a new instance of the fragment later needs to be 1310 * created, the data you place in the Bundle here will be available 1311 * in the Bundle given to {@link #onCreate(Bundle)}, 1312 * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}, and 1313 * {@link #onActivityCreated(Bundle)}. 1314 * 1315 * <p>This corresponds to {@link Activity#onSaveInstanceState(Bundle) 1316 * Activity.onSaveInstanceState(Bundle)} and most of the discussion there 1317 * applies here as well. Note however: <em>this method may be called 1318 * at any time before {@link #onDestroy()}</em>. There are many situations 1319 * where a fragment may be mostly torn down (such as when placed on the 1320 * back stack with no UI showing), but its state will not be saved until 1321 * its owning activity actually needs to save its state. 1322 * 1323 * @param outState Bundle in which to place your saved state. 1324 */ 1325 public void onSaveInstanceState(Bundle outState) { 1326 } 1327 1328 public void onConfigurationChanged(Configuration newConfig) { 1329 mCalled = true; 1330 } 1331 1332 /** 1333 * Called when the Fragment is no longer resumed. This is generally 1334 * tied to {@link Activity#onPause() Activity.onPause} of the containing 1335 * Activity's lifecycle. 1336 */ 1337 public void onPause() { 1338 mCalled = true; 1339 } 1340 1341 /** 1342 * Called when the Fragment is no longer started. This is generally 1343 * tied to {@link Activity#onStop() Activity.onStop} of the containing 1344 * Activity's lifecycle. 1345 */ 1346 public void onStop() { 1347 mCalled = true; 1348 } 1349 1350 public void onLowMemory() { 1351 mCalled = true; 1352 } 1353 1354 public void onTrimMemory(int level) { 1355 mCalled = true; 1356 } 1357 1358 /** 1359 * Called when the view previously created by {@link #onCreateView} has 1360 * been detached from the fragment. The next time the fragment needs 1361 * to be displayed, a new view will be created. This is called 1362 * after {@link #onStop()} and before {@link #onDestroy()}. It is called 1363 * <em>regardless</em> of whether {@link #onCreateView} returned a 1364 * non-null view. Internally it is called after the view's state has 1365 * been saved but before it has been removed from its parent. 1366 */ 1367 public void onDestroyView() { 1368 mCalled = true; 1369 } 1370 1371 /** 1372 * Called when the fragment is no longer in use. This is called 1373 * after {@link #onStop()} and before {@link #onDetach()}. 1374 */ 1375 public void onDestroy() { 1376 mCalled = true; 1377 //Log.v("foo", "onDestroy: mCheckedForLoaderManager=" + mCheckedForLoaderManager 1378 // + " mLoaderManager=" + mLoaderManager); 1379 if (!mCheckedForLoaderManager) { 1380 mCheckedForLoaderManager = true; 1381 mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, false); 1382 } 1383 if (mLoaderManager != null) { 1384 mLoaderManager.doDestroy(); 1385 } 1386 } 1387 1388 /** 1389 * Called by the fragment manager once this fragment has been removed, 1390 * so that we don't have any left-over state if the application decides 1391 * to re-use the instance. This only clears state that the framework 1392 * internally manages, not things the application sets. 1393 */ 1394 void initState() { 1395 mIndex = -1; 1396 mWho = null; 1397 mAdded = false; 1398 mRemoving = false; 1399 mResumed = false; 1400 mFromLayout = false; 1401 mInLayout = false; 1402 mRestored = false; 1403 mBackStackNesting = 0; 1404 mFragmentManager = null; 1405 mActivity = null; 1406 mFragmentId = 0; 1407 mContainerId = 0; 1408 mTag = null; 1409 mHidden = false; 1410 mDetached = false; 1411 mRetaining = false; 1412 mLoaderManager = null; 1413 mLoadersStarted = false; 1414 mCheckedForLoaderManager = false; 1415 } 1416 1417 /** 1418 * Called when the fragment is no longer attached to its activity. This 1419 * is called after {@link #onDestroy()}. 1420 */ 1421 public void onDetach() { 1422 mCalled = true; 1423 } 1424 1425 /** 1426 * Initialize the contents of the Activity's standard options menu. You 1427 * should place your menu items in to <var>menu</var>. For this method 1428 * to be called, you must have first called {@link #setHasOptionsMenu}. See 1429 * {@link Activity#onCreateOptionsMenu(Menu) Activity.onCreateOptionsMenu} 1430 * for more information. 1431 * 1432 * @param menu The options menu in which you place your items. 1433 * 1434 * @see #setHasOptionsMenu 1435 * @see #onPrepareOptionsMenu 1436 * @see #onOptionsItemSelected 1437 */ 1438 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 1439 } 1440 1441 /** 1442 * Prepare the Screen's standard options menu to be displayed. This is 1443 * called right before the menu is shown, every time it is shown. You can 1444 * use this method to efficiently enable/disable items or otherwise 1445 * dynamically modify the contents. See 1446 * {@link Activity#onPrepareOptionsMenu(Menu) Activity.onPrepareOptionsMenu} 1447 * for more information. 1448 * 1449 * @param menu The options menu as last shown or first initialized by 1450 * onCreateOptionsMenu(). 1451 * 1452 * @see #setHasOptionsMenu 1453 * @see #onCreateOptionsMenu 1454 */ 1455 public void onPrepareOptionsMenu(Menu menu) { 1456 } 1457 1458 /** 1459 * Called when this fragment's option menu items are no longer being 1460 * included in the overall options menu. Receiving this call means that 1461 * the menu needed to be rebuilt, but this fragment's items were not 1462 * included in the newly built menu (its {@link #onCreateOptionsMenu(Menu, MenuInflater)} 1463 * was not called). 1464 */ 1465 public void onDestroyOptionsMenu() { 1466 } 1467 1468 /** 1469 * This hook is called whenever an item in your options menu is selected. 1470 * The default implementation simply returns false to have the normal 1471 * processing happen (calling the item's Runnable or sending a message to 1472 * its Handler as appropriate). You can use this method for any items 1473 * for which you would like to do processing without those other 1474 * facilities. 1475 * 1476 * <p>Derived classes should call through to the base class for it to 1477 * perform the default menu handling. 1478 * 1479 * @param item The menu item that was selected. 1480 * 1481 * @return boolean Return false to allow normal menu processing to 1482 * proceed, true to consume it here. 1483 * 1484 * @see #onCreateOptionsMenu 1485 */ 1486 public boolean onOptionsItemSelected(MenuItem item) { 1487 return false; 1488 } 1489 1490 /** 1491 * This hook is called whenever the options menu is being closed (either by the user canceling 1492 * the menu with the back/menu button, or when an item is selected). 1493 * 1494 * @param menu The options menu as last shown or first initialized by 1495 * onCreateOptionsMenu(). 1496 */ 1497 public void onOptionsMenuClosed(Menu menu) { 1498 } 1499 1500 /** 1501 * Called when a context menu for the {@code view} is about to be shown. 1502 * Unlike {@link #onCreateOptionsMenu}, this will be called every 1503 * time the context menu is about to be shown and should be populated for 1504 * the view (or item inside the view for {@link AdapterView} subclasses, 1505 * this can be found in the {@code menuInfo})). 1506 * <p> 1507 * Use {@link #onContextItemSelected(android.view.MenuItem)} to know when an 1508 * item has been selected. 1509 * <p> 1510 * The default implementation calls up to 1511 * {@link Activity#onCreateContextMenu Activity.onCreateContextMenu}, though 1512 * you can not call this implementation if you don't want that behavior. 1513 * <p> 1514 * It is not safe to hold onto the context menu after this method returns. 1515 * {@inheritDoc} 1516 */ 1517 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { 1518 getActivity().onCreateContextMenu(menu, v, menuInfo); 1519 } 1520 1521 /** 1522 * Registers a context menu to be shown for the given view (multiple views 1523 * can show the context menu). This method will set the 1524 * {@link OnCreateContextMenuListener} on the view to this fragment, so 1525 * {@link #onCreateContextMenu(ContextMenu, View, ContextMenuInfo)} will be 1526 * called when it is time to show the context menu. 1527 * 1528 * @see #unregisterForContextMenu(View) 1529 * @param view The view that should show a context menu. 1530 */ 1531 public void registerForContextMenu(View view) { 1532 view.setOnCreateContextMenuListener(this); 1533 } 1534 1535 /** 1536 * Prevents a context menu to be shown for the given view. This method will 1537 * remove the {@link OnCreateContextMenuListener} on the view. 1538 * 1539 * @see #registerForContextMenu(View) 1540 * @param view The view that should stop showing a context menu. 1541 */ 1542 public void unregisterForContextMenu(View view) { 1543 view.setOnCreateContextMenuListener(null); 1544 } 1545 1546 /** 1547 * This hook is called whenever an item in a context menu is selected. The 1548 * default implementation simply returns false to have the normal processing 1549 * happen (calling the item's Runnable or sending a message to its Handler 1550 * as appropriate). You can use this method for any items for which you 1551 * would like to do processing without those other facilities. 1552 * <p> 1553 * Use {@link MenuItem#getMenuInfo()} to get extra information set by the 1554 * View that added this menu item. 1555 * <p> 1556 * Derived classes should call through to the base class for it to perform 1557 * the default menu handling. 1558 * 1559 * @param item The context menu item that was selected. 1560 * @return boolean Return false to allow normal context menu processing to 1561 * proceed, true to consume it here. 1562 */ 1563 public boolean onContextItemSelected(MenuItem item) { 1564 return false; 1565 } 1566 1567 /** 1568 * Print the Fragments's state into the given stream. 1569 * 1570 * @param prefix Text to print at the front of each line. 1571 * @param fd The raw file descriptor that the dump is being sent to. 1572 * @param writer The PrintWriter to which you should dump your state. This will be 1573 * closed for you after you return. 1574 * @param args additional arguments to the dump request. 1575 */ 1576 public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { 1577 writer.print(prefix); writer.print("mFragmentId=#"); 1578 writer.print(Integer.toHexString(mFragmentId)); 1579 writer.print(" mContainerId=#"); 1580 writer.print(Integer.toHexString(mContainerId)); 1581 writer.print(" mTag="); writer.println(mTag); 1582 writer.print(prefix); writer.print("mState="); writer.print(mState); 1583 writer.print(" mIndex="); writer.print(mIndex); 1584 writer.print(" mWho="); writer.print(mWho); 1585 writer.print(" mBackStackNesting="); writer.println(mBackStackNesting); 1586 writer.print(prefix); writer.print("mAdded="); writer.print(mAdded); 1587 writer.print(" mRemoving="); writer.print(mRemoving); 1588 writer.print(" mResumed="); writer.print(mResumed); 1589 writer.print(" mFromLayout="); writer.print(mFromLayout); 1590 writer.print(" mInLayout="); writer.println(mInLayout); 1591 writer.print(prefix); writer.print("mHidden="); writer.print(mHidden); 1592 writer.print(" mDetached="); writer.print(mDetached); 1593 writer.print(" mMenuVisible="); writer.print(mMenuVisible); 1594 writer.print(" mHasMenu="); writer.println(mHasMenu); 1595 writer.print(prefix); writer.print("mRetainInstance="); writer.print(mRetainInstance); 1596 writer.print(" mRetaining="); writer.print(mRetaining); 1597 writer.print(" mUserVisibleHint="); writer.println(mUserVisibleHint); 1598 if (mFragmentManager != null) { 1599 writer.print(prefix); writer.print("mFragmentManager="); 1600 writer.println(mFragmentManager); 1601 } 1602 if (mActivity != null) { 1603 writer.print(prefix); writer.print("mActivity="); 1604 writer.println(mActivity); 1605 } 1606 if (mParentFragment != null) { 1607 writer.print(prefix); writer.print("mParentFragment="); 1608 writer.println(mParentFragment); 1609 } 1610 if (mArguments != null) { 1611 writer.print(prefix); writer.print("mArguments="); writer.println(mArguments); 1612 } 1613 if (mSavedFragmentState != null) { 1614 writer.print(prefix); writer.print("mSavedFragmentState="); 1615 writer.println(mSavedFragmentState); 1616 } 1617 if (mSavedViewState != null) { 1618 writer.print(prefix); writer.print("mSavedViewState="); 1619 writer.println(mSavedViewState); 1620 } 1621 if (mTarget != null) { 1622 writer.print(prefix); writer.print("mTarget="); writer.print(mTarget); 1623 writer.print(" mTargetRequestCode="); 1624 writer.println(mTargetRequestCode); 1625 } 1626 if (mNextAnim != 0) { 1627 writer.print(prefix); writer.print("mNextAnim="); writer.println(mNextAnim); 1628 } 1629 if (mContainer != null) { 1630 writer.print(prefix); writer.print("mContainer="); writer.println(mContainer); 1631 } 1632 if (mView != null) { 1633 writer.print(prefix); writer.print("mView="); writer.println(mView); 1634 } 1635 if (mAnimatingAway != null) { 1636 writer.print(prefix); writer.print("mAnimatingAway="); writer.println(mAnimatingAway); 1637 writer.print(prefix); writer.print("mStateAfterAnimating="); 1638 writer.println(mStateAfterAnimating); 1639 } 1640 if (mLoaderManager != null) { 1641 writer.print(prefix); writer.println("Loader Manager:"); 1642 mLoaderManager.dump(prefix + " ", fd, writer, args); 1643 } 1644 if (mChildFragmentManager != null) { 1645 writer.print(prefix); writer.println("Child " + mChildFragmentManager + ":"); 1646 mChildFragmentManager.dump(prefix + " ", fd, writer, args); 1647 } 1648 } 1649 1650 Fragment findFragmentByWho(String who) { 1651 if (who.equals(mWho)) { 1652 return this; 1653 } 1654 if (mChildFragmentManager != null) { 1655 return mChildFragmentManager.findFragmentByWho(who); 1656 } 1657 return null; 1658 } 1659 1660 void instantiateChildFragmentManager() { 1661 mChildFragmentManager = new FragmentManagerImpl(); 1662 mChildFragmentManager.attachActivity(mActivity, new FragmentContainer() { 1663 @Override 1664 public View findViewById(int id) { 1665 if (mView == null) { 1666 throw new IllegalStateException("Fragment does not have a view"); 1667 } 1668 return mView.findViewById(id); 1669 } 1670 }, this); 1671 } 1672 1673 void performCreate(Bundle savedInstanceState) { 1674 if (mChildFragmentManager != null) { 1675 mChildFragmentManager.noteStateNotSaved(); 1676 } 1677 mCalled = false; 1678 onCreate(savedInstanceState); 1679 if (!mCalled) { 1680 throw new SuperNotCalledException("Fragment " + this 1681 + " did not call through to super.onCreate()"); 1682 } 1683 if (savedInstanceState != null) { 1684 Parcelable p = savedInstanceState.getParcelable(Activity.FRAGMENTS_TAG); 1685 if (p != null) { 1686 if (mChildFragmentManager == null) { 1687 instantiateChildFragmentManager(); 1688 } 1689 mChildFragmentManager.restoreAllState(p, null); 1690 mChildFragmentManager.dispatchCreate(); 1691 } 1692 } 1693 } 1694 1695 View performCreateView(LayoutInflater inflater, ViewGroup container, 1696 Bundle savedInstanceState) { 1697 if (mChildFragmentManager != null) { 1698 mChildFragmentManager.noteStateNotSaved(); 1699 } 1700 return onCreateView(inflater, container, savedInstanceState); 1701 } 1702 1703 void performActivityCreated(Bundle savedInstanceState) { 1704 if (mChildFragmentManager != null) { 1705 mChildFragmentManager.noteStateNotSaved(); 1706 } 1707 mCalled = false; 1708 onActivityCreated(savedInstanceState); 1709 if (!mCalled) { 1710 throw new SuperNotCalledException("Fragment " + this 1711 + " did not call through to super.onActivityCreated()"); 1712 } 1713 if (mChildFragmentManager != null) { 1714 mChildFragmentManager.dispatchActivityCreated(); 1715 } 1716 } 1717 1718 void performStart() { 1719 if (mChildFragmentManager != null) { 1720 mChildFragmentManager.noteStateNotSaved(); 1721 mChildFragmentManager.execPendingActions(); 1722 } 1723 mCalled = false; 1724 onStart(); 1725 if (!mCalled) { 1726 throw new SuperNotCalledException("Fragment " + this 1727 + " did not call through to super.onStart()"); 1728 } 1729 if (mChildFragmentManager != null) { 1730 mChildFragmentManager.dispatchStart(); 1731 } 1732 if (mLoaderManager != null) { 1733 mLoaderManager.doReportStart(); 1734 } 1735 } 1736 1737 void performResume() { 1738 if (mChildFragmentManager != null) { 1739 mChildFragmentManager.noteStateNotSaved(); 1740 mChildFragmentManager.execPendingActions(); 1741 } 1742 mCalled = false; 1743 onResume(); 1744 if (!mCalled) { 1745 throw new SuperNotCalledException("Fragment " + this 1746 + " did not call through to super.onResume()"); 1747 } 1748 if (mChildFragmentManager != null) { 1749 mChildFragmentManager.dispatchResume(); 1750 mChildFragmentManager.execPendingActions(); 1751 } 1752 } 1753 1754 void performConfigurationChanged(Configuration newConfig) { 1755 onConfigurationChanged(newConfig); 1756 if (mChildFragmentManager != null) { 1757 mChildFragmentManager.dispatchConfigurationChanged(newConfig); 1758 } 1759 } 1760 1761 void performLowMemory() { 1762 onLowMemory(); 1763 if (mChildFragmentManager != null) { 1764 mChildFragmentManager.dispatchLowMemory(); 1765 } 1766 } 1767 1768 void performTrimMemory(int level) { 1769 onTrimMemory(level); 1770 if (mChildFragmentManager != null) { 1771 mChildFragmentManager.dispatchTrimMemory(level); 1772 } 1773 } 1774 1775 boolean performCreateOptionsMenu(Menu menu, MenuInflater inflater) { 1776 boolean show = false; 1777 if (!mHidden) { 1778 if (mHasMenu && mMenuVisible) { 1779 show = true; 1780 onCreateOptionsMenu(menu, inflater); 1781 } 1782 if (mChildFragmentManager != null) { 1783 show |= mChildFragmentManager.dispatchCreateOptionsMenu(menu, inflater); 1784 } 1785 } 1786 return show; 1787 } 1788 1789 boolean performPrepareOptionsMenu(Menu menu) { 1790 boolean show = false; 1791 if (!mHidden) { 1792 if (mHasMenu && mMenuVisible) { 1793 show = true; 1794 onPrepareOptionsMenu(menu); 1795 } 1796 if (mChildFragmentManager != null) { 1797 show |= mChildFragmentManager.dispatchPrepareOptionsMenu(menu); 1798 } 1799 } 1800 return show; 1801 } 1802 1803 boolean performOptionsItemSelected(MenuItem item) { 1804 if (!mHidden) { 1805 if (mHasMenu && mMenuVisible) { 1806 if (onOptionsItemSelected(item)) { 1807 return true; 1808 } 1809 } 1810 if (mChildFragmentManager != null) { 1811 if (mChildFragmentManager.dispatchOptionsItemSelected(item)) { 1812 return true; 1813 } 1814 } 1815 } 1816 return false; 1817 } 1818 1819 boolean performContextItemSelected(MenuItem item) { 1820 if (!mHidden) { 1821 if (onContextItemSelected(item)) { 1822 return true; 1823 } 1824 if (mChildFragmentManager != null) { 1825 if (mChildFragmentManager.dispatchContextItemSelected(item)) { 1826 return true; 1827 } 1828 } 1829 } 1830 return false; 1831 } 1832 1833 void performOptionsMenuClosed(Menu menu) { 1834 if (!mHidden) { 1835 if (mHasMenu && mMenuVisible) { 1836 onOptionsMenuClosed(menu); 1837 } 1838 if (mChildFragmentManager != null) { 1839 mChildFragmentManager.dispatchOptionsMenuClosed(menu); 1840 } 1841 } 1842 } 1843 1844 void performSaveInstanceState(Bundle outState) { 1845 onSaveInstanceState(outState); 1846 if (mChildFragmentManager != null) { 1847 Parcelable p = mChildFragmentManager.saveAllState(); 1848 if (p != null) { 1849 outState.putParcelable(Activity.FRAGMENTS_TAG, p); 1850 } 1851 } 1852 } 1853 1854 void performPause() { 1855 if (mChildFragmentManager != null) { 1856 mChildFragmentManager.dispatchPause(); 1857 } 1858 mCalled = false; 1859 onPause(); 1860 if (!mCalled) { 1861 throw new SuperNotCalledException("Fragment " + this 1862 + " did not call through to super.onPause()"); 1863 } 1864 } 1865 1866 void performStop() { 1867 if (mChildFragmentManager != null) { 1868 mChildFragmentManager.dispatchStop(); 1869 } 1870 mCalled = false; 1871 onStop(); 1872 if (!mCalled) { 1873 throw new SuperNotCalledException("Fragment " + this 1874 + " did not call through to super.onStop()"); 1875 } 1876 1877 if (mLoadersStarted) { 1878 mLoadersStarted = false; 1879 if (!mCheckedForLoaderManager) { 1880 mCheckedForLoaderManager = true; 1881 mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, false); 1882 } 1883 if (mLoaderManager != null) { 1884 if (mActivity == null || !mActivity.mChangingConfigurations) { 1885 mLoaderManager.doStop(); 1886 } else { 1887 mLoaderManager.doRetain(); 1888 } 1889 } 1890 } 1891 } 1892 1893 void performDestroyView() { 1894 if (mChildFragmentManager != null) { 1895 mChildFragmentManager.dispatchDestroyView(); 1896 } 1897 mCalled = false; 1898 onDestroyView(); 1899 if (!mCalled) { 1900 throw new SuperNotCalledException("Fragment " + this 1901 + " did not call through to super.onDestroyView()"); 1902 } 1903 if (mLoaderManager != null) { 1904 mLoaderManager.doReportNextStart(); 1905 } 1906 } 1907 1908 void performDestroy() { 1909 if (mChildFragmentManager != null) { 1910 mChildFragmentManager.dispatchDestroy(); 1911 } 1912 mCalled = false; 1913 onDestroy(); 1914 if (!mCalled) { 1915 throw new SuperNotCalledException("Fragment " + this 1916 + " did not call through to super.onDestroy()"); 1917 } 1918 } 1919 } 1920