Fragment.java revision 5164246d7e47b9c995ca1e1587f3056eb777f60b
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 17package android.app; 18 19import android.animation.Animator; 20import android.content.ComponentCallbacks; 21import android.content.Context; 22import android.content.Intent; 23import android.content.res.Configuration; 24import android.os.Bundle; 25import android.os.Parcel; 26import android.os.Parcelable; 27import android.util.AndroidRuntimeException; 28import android.util.AttributeSet; 29import android.util.SparseArray; 30import android.view.ContextMenu; 31import android.view.LayoutInflater; 32import android.view.Menu; 33import android.view.MenuInflater; 34import android.view.MenuItem; 35import android.view.View; 36import android.view.ViewGroup; 37import android.view.ContextMenu.ContextMenuInfo; 38import android.view.View.OnCreateContextMenuListener; 39import android.widget.AdapterView; 40 41import java.io.FileDescriptor; 42import java.io.PrintWriter; 43import java.util.HashMap; 44 45final class FragmentState implements Parcelable { 46 final String mClassName; 47 final int mIndex; 48 final boolean mFromLayout; 49 final int mFragmentId; 50 final int mContainerId; 51 final String mTag; 52 final boolean mRetainInstance; 53 final Bundle mArguments; 54 55 Bundle mSavedFragmentState; 56 57 Fragment mInstance; 58 59 public FragmentState(Fragment frag) { 60 mClassName = frag.getClass().getName(); 61 mIndex = frag.mIndex; 62 mFromLayout = frag.mFromLayout; 63 mFragmentId = frag.mFragmentId; 64 mContainerId = frag.mContainerId; 65 mTag = frag.mTag; 66 mRetainInstance = frag.mRetainInstance; 67 mArguments = frag.mArguments; 68 } 69 70 public FragmentState(Parcel in) { 71 mClassName = in.readString(); 72 mIndex = in.readInt(); 73 mFromLayout = in.readInt() != 0; 74 mFragmentId = in.readInt(); 75 mContainerId = in.readInt(); 76 mTag = in.readString(); 77 mRetainInstance = in.readInt() != 0; 78 mArguments = in.readBundle(); 79 mSavedFragmentState = in.readBundle(); 80 } 81 82 public Fragment instantiate(Activity activity) { 83 if (mInstance != null) { 84 return mInstance; 85 } 86 87 if (mArguments != null) { 88 mArguments.setClassLoader(activity.getClassLoader()); 89 } 90 91 mInstance = Fragment.instantiate(activity, mClassName, mArguments); 92 93 if (mSavedFragmentState != null) { 94 mSavedFragmentState.setClassLoader(activity.getClassLoader()); 95 mInstance.mSavedFragmentState = mSavedFragmentState; 96 } 97 mInstance.setIndex(mIndex); 98 mInstance.mFromLayout = mFromLayout; 99 mInstance.mFragmentId = mFragmentId; 100 mInstance.mContainerId = mContainerId; 101 mInstance.mTag = mTag; 102 mInstance.mRetainInstance = mRetainInstance; 103 mInstance.mFragmentManager = activity.mFragments; 104 105 return mInstance; 106 } 107 108 public int describeContents() { 109 return 0; 110 } 111 112 public void writeToParcel(Parcel dest, int flags) { 113 dest.writeString(mClassName); 114 dest.writeInt(mIndex); 115 dest.writeInt(mFromLayout ? 1 : 0); 116 dest.writeInt(mFragmentId); 117 dest.writeInt(mContainerId); 118 dest.writeString(mTag); 119 dest.writeInt(mRetainInstance ? 1 : 0); 120 dest.writeBundle(mArguments); 121 dest.writeBundle(mSavedFragmentState); 122 } 123 124 public static final Parcelable.Creator<FragmentState> CREATOR 125 = new Parcelable.Creator<FragmentState>() { 126 public FragmentState createFromParcel(Parcel in) { 127 return new FragmentState(in); 128 } 129 130 public FragmentState[] newArray(int size) { 131 return new FragmentState[size]; 132 } 133 }; 134} 135 136/** 137 * A Fragment is a piece of an application's user interface or behavior 138 * that can be placed in an {@link Activity}. Interaction with fragments 139 * is done through {@link FragmentManager}, which can be obtained via 140 * {@link Activity#getFragmentManager() Activity.getFragmentManager()} and 141 * {@link Fragment#getFragmentManager() Fragment.getFragmentManager()}. 142 * 143 * <p>The Fragment class can be used many ways to achieve a wide variety of 144 * results. It is core, it represents a particular operation or interface 145 * that is running within a larger {@link Activity}. A Fragment is closely 146 * tied to the Activity it is in, and can not be used apart from one. Though 147 * Fragment defines its own lifecycle, that lifecycle is dependent on its 148 * activity: if the activity is stopped, no fragments inside of it can be 149 * started; when the activity is destroyed, all fragments will be destroyed. 150 * 151 * <p>All subclasses of Fragment must include a public empty constructor. 152 * The framework will often re-instantiate a fragment class when needed, 153 * in particular during state restore, and needs to be able to find this 154 * constructor to instantiate it. If the empty constructor is not available, 155 * a runtime exception will occur in some cases during state restore. 156 * 157 * <p>Topics covered here: 158 * <ol> 159 * <li><a href="#Lifecycle">Lifecycle</a> 160 * <li><a href="#Layout">Layout</a> 161 * <li><a href="#BackStack">Back Stack</a> 162 * </ol> 163 * 164 * <a name="Lifecycle"></a> 165 * <h3>Lifecycle</h3> 166 * 167 * <p>Though a Fragment's lifecycle is tied to its owning activity, it has 168 * its own wrinkle on the standard activity lifecycle. It includes basic 169 * activity lifecycle methods such as {@link #onResume}, but also important 170 * are methods related to interactions with the activity and UI generation. 171 * 172 * <p>The core series of lifecycle methods that are called to bring a fragment 173 * up to resumed state (interacting with the user) are: 174 * 175 * <ol> 176 * <li> {@link #onAttach} called once the fragment is associated with its activity. 177 * <li> {@link #onCreate} called to do initial creation of the fragment. 178 * <li> {@link #onCreateView} creates and returns the view hierarchy associated 179 * with the fragment. 180 * <li> {@link #onActivityCreated} tells the fragment that its activity has 181 * completed its own {@link Activity#onCreate Activity.onCreaate}. 182 * <li> {@link #onStart} makes the fragment visible to the user (based on its 183 * containing activity being started). 184 * <li> {@link #onResume} makes the fragment interacting with the user (based on its 185 * containing activity being resumed). 186 * </ol> 187 * 188 * <p>As a fragment is no longer being used, it goes through a reverse 189 * series of callbacks: 190 * 191 * <ol> 192 * <li> {@link #onPause} fragment is no longer interacting with the user either 193 * because its activity is being paused or a fragment operation is modifying it 194 * in the activity. 195 * <li> {@link #onStop} fragment is no longer visible to the user either 196 * because its activity is being stopped or a fragment operation is modifying it 197 * in the activity. 198 * <li> {@link #onDestroyView} allows the fragment to clean up resources 199 * associated with its View. 200 * <li> {@link #onDestroy} called to do final cleanup of the fragment's state. 201 * <li> {@link #onDetach} called immediately prior to the fragment no longer 202 * being associated with its activity. 203 * </ol> 204 * 205 * <a name="Layout"></a> 206 * <h3>Layout</h3> 207 * 208 * <p>Fragments can be used as part of your application's layout, allowing 209 * you to better modularize your code and more easily adjust your user 210 * interface to the screen it is running on. As an example, we can look 211 * at a simple program consisting of a list of items, and display of the 212 * details of each item.</p> 213 * 214 * <p>An activity's layout XML can include <code><fragment></code> tags 215 * to embed fragment instances inside of the layout. For example, here is 216 * a simple layout that embeds one fragment:</p> 217 * 218 * {@sample development/samples/ApiDemos/res/layout/fragment_layout.xml layout} 219 * 220 * <p>The layout is installed in the activity in the normal way:</p> 221 * 222 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java 223 * main} 224 * 225 * <p>The titles fragment, showing a list of titles, is very simple, relying 226 * on {@link ListFragment} for most of its work. Note the implementation of 227 * clicking an item, which can either update 228 * the content of the details fragment or start a new activity show the 229 * details depending on whether the current activity's layout can show the 230 * details.</p> 231 * 232 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java 233 * titles} 234 * 235 * <p>The details fragment showing the contents of selected item here just 236 * displays a string of text based on an index of a string array built in to 237 * the app:</p> 238 * 239 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java 240 * details} 241 * 242 * <p>In this case when the user clicks on a title, there is no details 243 * fragment in the current activity, so the title title fragment's click code will 244 * launch a new activity to display the details fragment:</p> 245 * 246 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java 247 * details_activity} 248 * 249 * <p>However the screen may be large enough to show both the list of titles 250 * and details about the currently selected title. To use such a layout on 251 * a landscape screen, this alternative layout can be placed under layout-land:</p> 252 * 253 * {@sample development/samples/ApiDemos/res/layout-land/fragment_layout.xml layout} 254 * 255 * <p>Note how the prior code will adjust to this alternative UI flow: the 256 * titles fragment will now show its text inside of its activity, and the 257 * details activity will finish of it finds itself running in a configuration 258 * where the details can be shown inline. 259 * 260 * <p>When a configuration change causes the activity hosting these fragments 261 * to restart, its new instance may use a different layout that doesn't 262 * include the same fragments as the previous layout. In this case all of 263 * the previous fragments will still be instantiated and running in the new 264 * instance; however, any that are no longer associated with a <fragment> 265 * tag in the view hierarchy will not have their content view created and will 266 * return false from {@link #isInLayout}. 267 * 268 * <p>The attributes of the <fragment> tag are used to control the 269 * LayoutParams provider when attaching the fragment's view to the parent 270 * container. They can alse be parsed by the fragment in {@link #onInflate} 271 * as parameters. 272 * 273 * <p>The fragment being instantiated must have some kind of unique identifier 274 * so that it can be re-associated with a previous instance if the parent 275 * activity needs to be destroyed and recreated. This can be provided these 276 * ways: 277 * 278 * <ul> 279 * <li>If nothing is explicitly supplied, the view ID of the container will 280 * be used. 281 * <li><code>android:tag</code> can be used in <fragment> to provide 282 * a specific tag name for the fragment. 283 * <li><code>android:id</code> can be used in <fragment> to provide 284 * a specific identifier for the fragment. 285 * </ul> 286 * 287 * <a name="BackStack"></a> 288 * <h3>Back Stack</h3> 289 * 290 * <p>The transaction in which fragments are modified can be placed on an 291 * internal back-stack of the owning activity. When the user presses back 292 * in the activity, any transactions on the back stack are popped off before 293 * the activity itself is finished. 294 * 295 * <p>For example, consider this simple fragment that is instantiated with 296 * an integer argument and displays that in a TextView in its UI:</p> 297 * 298 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentStack.java 299 * fragment} 300 * 301 * <p>A function that creates a new instance of the fragment, replacing 302 * whatever current fragment instance is being shown and pushing that change 303 * on to the back stack could be written as: 304 * 305 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentStack.java 306 * add_stack} 307 * 308 * <p>After each call to this function, a new entry is on the stack, and 309 * pressing back will pop it to return the user to whatever previous state 310 * the activity UI was in. 311 */ 312public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener { 313 private static final HashMap<String, Class<?>> sClassMap = 314 new HashMap<String, Class<?>>(); 315 316 static final int INITIALIZING = 0; // Not yet created. 317 static final int CREATED = 1; // Created. 318 static final int ACTIVITY_CREATED = 2; // The activity has finished its creation. 319 static final int STARTED = 3; // Created and started, not resumed. 320 static final int RESUMED = 4; // Created started and resumed. 321 322 int mState = INITIALIZING; 323 324 // When instantiated from saved state, this is the saved state. 325 Bundle mSavedFragmentState; 326 SparseArray<Parcelable> mSavedViewState; 327 328 // Index into active fragment array. 329 int mIndex = -1; 330 331 // Internal unique name for this fragment; 332 String mWho; 333 334 // Construction arguments; 335 Bundle mArguments; 336 337 // Target fragment. 338 Fragment mTarget; 339 340 // Target request code. 341 int mTargetRequestCode; 342 343 // True if the fragment is in the list of added fragments. 344 boolean mAdded; 345 346 // True if the fragment is in the resumed state. 347 boolean mResumed; 348 349 // Set to true if this fragment was instantiated from a layout file. 350 boolean mFromLayout; 351 352 // Set to true when the view has actually been inflated in its layout. 353 boolean mInLayout; 354 355 // Number of active back stack entries this fragment is in. 356 int mBackStackNesting; 357 358 // The fragment manager we are associated with. Set as soon as the 359 // fragment is used in a transaction; cleared after it has been removed 360 // from all transactions. 361 FragmentManager mFragmentManager; 362 363 // Set as soon as a fragment is added to a transaction (or removed), 364 // to be able to do validation. 365 Activity mImmediateActivity; 366 367 // Activity this fragment is attached to. 368 Activity mActivity; 369 370 // The optional identifier for this fragment -- either the container ID if it 371 // was dynamically added to the view hierarchy, or the ID supplied in 372 // layout. 373 int mFragmentId; 374 375 // When a fragment is being dynamically added to the view hierarchy, this 376 // is the identifier of the parent container it is being added to. 377 int mContainerId; 378 379 // The optional named tag for this fragment -- usually used to find 380 // fragments that are not part of the layout. 381 String mTag; 382 383 // Set to true when the app has requested that this fragment be hidden 384 // from the user. 385 boolean mHidden; 386 387 // If set this fragment would like its instance retained across 388 // configuration changes. 389 boolean mRetainInstance; 390 391 // If set this fragment is being retained across the current config change. 392 boolean mRetaining; 393 394 // If set this fragment has menu items to contribute. 395 boolean mHasMenu; 396 397 // Used to verify that subclasses call through to super class. 398 boolean mCalled; 399 400 // If app has requested a specific animation, this is the one to use. 401 int mNextAnim; 402 403 // The parent container of the fragment after dynamically added to UI. 404 ViewGroup mContainer; 405 406 // The View generated for this fragment. 407 View mView; 408 409 LoaderManagerImpl mLoaderManager; 410 boolean mLoadersStarted; 411 boolean mCheckedForLoaderManager; 412 413 /** 414 * Thrown by {@link Fragment#instantiate(Context, String, Bundle)} when 415 * there is an instantiation failure. 416 */ 417 static public class InstantiationException extends AndroidRuntimeException { 418 public InstantiationException(String msg, Exception cause) { 419 super(msg, cause); 420 } 421 } 422 423 /** 424 * Default constructor. <strong>Every</strong> fragment must have an 425 * empty constructor, so it can be instantiated when restoring its 426 * activity's state. It is strongly recommended that subclasses do not 427 * have other constructors with parameters, since these constructors 428 * will not be called when the fragment is re-instantiated; instead, 429 * arguments can be supplied by the caller with {@link #setArguments} 430 * and later retrieved by the Fragment with {@link #getArguments}. 431 * 432 * <p>Applications should generally not implement a constructor. The 433 * first place application code an run where the fragment is ready to 434 * be used is in {@link #onAttach(Activity)}, the point where the fragment 435 * is actually associated with its activity. Some applications may also 436 * want to implement {@link #onInflate} to retrieve attributes from a 437 * layout resource, though should take care here because this happens for 438 * the fragment is attached to its activity. 439 */ 440 public Fragment() { 441 } 442 443 /** 444 * Like {@link #instantiate(Context, String, Bundle)} but with a null 445 * argument Bundle. 446 */ 447 public static Fragment instantiate(Context context, String fname) { 448 return instantiate(context, fname, null); 449 } 450 451 /** 452 * Create a new instance of a Fragment with the given class name. This is 453 * the same as calling its empty constructor. 454 * 455 * @param context The calling context being used to instantiate the fragment. 456 * This is currently just used to get its ClassLoader. 457 * @param fname The class name of the fragment to instantiate. 458 * @param args Bundle of arguments to supply to the fragment, which it 459 * can retrieve with {@link #getArguments()}. May be null. 460 * @return Returns a new fragment instance. 461 * @throws InstantiationException If there is a failure in instantiating 462 * the given fragment class. This is a runtime exception; it is not 463 * normally expected to happen. 464 */ 465 public static Fragment instantiate(Context context, String fname, Bundle args) { 466 try { 467 Class<?> clazz = sClassMap.get(fname); 468 if (clazz == null) { 469 // Class not found in the cache, see if it's real, and try to add it 470 clazz = context.getClassLoader().loadClass(fname); 471 sClassMap.put(fname, clazz); 472 } 473 Fragment f = (Fragment)clazz.newInstance(); 474 if (args != null) { 475 args.setClassLoader(f.getClass().getClassLoader()); 476 f.mArguments = args; 477 } 478 return f; 479 } catch (ClassNotFoundException e) { 480 throw new InstantiationException("Unable to instantiate fragment " + fname 481 + ": make sure class name exists, is public, and has an" 482 + " empty constructor that is public", e); 483 } catch (java.lang.InstantiationException e) { 484 throw new InstantiationException("Unable to instantiate fragment " + fname 485 + ": make sure class name exists, is public, and has an" 486 + " empty constructor that is public", e); 487 } catch (IllegalAccessException e) { 488 throw new InstantiationException("Unable to instantiate fragment " + fname 489 + ": make sure class name exists, is public, and has an" 490 + " empty constructor that is public", e); 491 } 492 } 493 494 void restoreViewState() { 495 if (mSavedViewState != null) { 496 mView.restoreHierarchyState(mSavedViewState); 497 mSavedViewState = null; 498 } 499 } 500 501 void setIndex(int index) { 502 mIndex = index; 503 mWho = "android:fragment:" + mIndex; 504 } 505 506 void clearIndex() { 507 mIndex = -1; 508 mWho = null; 509 } 510 511 /** 512 * Subclasses can not override equals(). 513 */ 514 @Override final public boolean equals(Object o) { 515 return super.equals(o); 516 } 517 518 /** 519 * Subclasses can not override hashCode(). 520 */ 521 @Override final public int hashCode() { 522 return super.hashCode(); 523 } 524 525 @Override 526 public String toString() { 527 StringBuilder sb = new StringBuilder(128); 528 sb.append("Fragment{"); 529 sb.append(Integer.toHexString(System.identityHashCode(this))); 530 if (mIndex >= 0) { 531 sb.append(" #"); 532 sb.append(mIndex); 533 } 534 if (mFragmentId != 0) { 535 sb.append(" id=0x"); 536 sb.append(Integer.toHexString(mFragmentId)); 537 } 538 if (mTag != null) { 539 sb.append(" "); 540 sb.append(mTag); 541 } 542 sb.append('}'); 543 return sb.toString(); 544 } 545 546 /** 547 * Return the identifier this fragment is known by. This is either 548 * the android:id value supplied in a layout or the container view ID 549 * supplied when adding the fragment. 550 */ 551 final public int getId() { 552 return mFragmentId; 553 } 554 555 /** 556 * Get the tag name of the fragment, if specified. 557 */ 558 final public String getTag() { 559 return mTag; 560 } 561 562 /** 563 * Supply the construction arguments for this fragment. This can only 564 * be called before the fragment has been attached to its activity; that 565 * is, you should call it immediately after constructing the fragment. The 566 * arguments supplied here will be retained across fragment destroy and 567 * creation. 568 */ 569 public void setArguments(Bundle args) { 570 if (mIndex >= 0) { 571 throw new IllegalStateException("Fragment already active"); 572 } 573 mArguments = args; 574 } 575 576 /** 577 * Return the arguments supplied when the fragment was instantiated, 578 * if any. 579 */ 580 final public Bundle getArguments() { 581 return mArguments; 582 } 583 584 /** 585 * Optional target for this fragment. This may be used, for example, 586 * if this fragment is being started by another, and when done wants to 587 * give a result back to the first. The target set here is retained 588 * across instances via {@link FragmentManager#putFragment 589 * FragmentManager.putFragment()}. 590 * 591 * @param fragment The fragment that is the target of this one. 592 * @param requestCode Optional request code, for convenience if you 593 * are going to call back with {@link #onActivityResult(int, int, Intent)}. 594 */ 595 public void setTargetFragment(Fragment fragment, int requestCode) { 596 mTarget = fragment; 597 mTargetRequestCode = requestCode; 598 } 599 600 /** 601 * Return the target fragment set by {@link #setTargetFragment}. 602 */ 603 final public Fragment getTargetFragment() { 604 return mTarget; 605 } 606 607 /** 608 * Return the target request code set by {@link #setTargetFragment}. 609 */ 610 final public int getTargetRequestCode() { 611 return mTargetRequestCode; 612 } 613 614 /** 615 * Return the Activity this fragment is currently associated with. 616 */ 617 final public Activity getActivity() { 618 return mActivity; 619 } 620 621 /** 622 * Return the FragmentManager for interacting with fragments associated 623 * with this fragment's activity. Note that this will be non-null slightly 624 * before {@link #getActivity()}, during the time from when the fragment is 625 * placed in a {@link FragmentTransaction} until it is committed and 626 * attached to its activity. 627 */ 628 final public FragmentManager getFragmentManager() { 629 return mFragmentManager; 630 } 631 632 /** 633 * Return true if the fragment is currently added to its activity. 634 */ 635 final public boolean isAdded() { 636 return mActivity != null && mActivity.mFragments.mAdded.contains(this); 637 } 638 639 /** 640 * Return true if the layout is included as part of an activity view 641 * hierarchy via the <fragment> tag. This will always be true when 642 * fragments are created through the <fragment> tag, <em>except</em> 643 * in the case where an old fragment is restored from a previous state and 644 * it does not appear in the layout of the current state. 645 */ 646 final public boolean isInLayout() { 647 return mInLayout; 648 } 649 650 /** 651 * Return true if the fragment is in the resumed state. This is true 652 * for the duration of {@link #onResume()} and {@link #onPause()} as well. 653 */ 654 final public boolean isResumed() { 655 return mResumed; 656 } 657 658 /** 659 * Return true if the fragment is currently visible to the user. This means 660 * it: (1) has been added, (2) has its view attached to the window, and 661 * (3) is not hidden. 662 */ 663 final public boolean isVisible() { 664 return isAdded() && !isHidden() && mView != null 665 && mView.getWindowToken() != null && mView.getVisibility() == View.VISIBLE; 666 } 667 668 /** 669 * Return true if the fragment has been hidden. By default fragments 670 * are shown. You can find out about changes to this state with 671 * {@link #onHiddenChanged}. Note that the hidden state is orthogonal 672 * to other states -- that is, to be visible to the user, a fragment 673 * must be both started and not hidden. 674 */ 675 final public boolean isHidden() { 676 return mHidden; 677 } 678 679 /** 680 * Called when the hidden state (as returned by {@link #isHidden()} of 681 * the fragment has changed. Fragments start out not hidden; this will 682 * be called whenever the fragment changes state from that. 683 * @param hidden True if the fragment is now hidden, false if it is not 684 * visible. 685 */ 686 public void onHiddenChanged(boolean hidden) { 687 } 688 689 /** 690 * Control whether a fragment instance is retained across Activity 691 * re-creation (such as from a configuration change). This can only 692 * be used with fragments not in the back stack. If set, the fragment 693 * lifecycle will be slightly different when an activity is recreated: 694 * <ul> 695 * <li> {@link #onDestroy()} will not be called (but {@link #onDetach()} still 696 * will be, because the fragment is being detached from its current activity). 697 * <li> {@link #onCreate(Bundle)} will not be called since the fragment 698 * is not being re-created. 699 * <li> {@link #onAttach(Activity)} and {@link #onActivityCreated(Bundle)} <b>will</b> 700 * still be called. 701 * </ul> 702 */ 703 public void setRetainInstance(boolean retain) { 704 mRetainInstance = retain; 705 } 706 707 final public boolean getRetainInstance() { 708 return mRetainInstance; 709 } 710 711 /** 712 * Report that this fragment would like to participate in populating 713 * the options menu by receiving a call to {@link #onCreateOptionsMenu} 714 * and related methods. 715 * 716 * @param hasMenu If true, the fragment has menu items to contribute. 717 */ 718 public void setHasOptionsMenu(boolean hasMenu) { 719 if (mHasMenu != hasMenu) { 720 mHasMenu = hasMenu; 721 if (isAdded() && !isHidden()) { 722 mActivity.invalidateOptionsMenu(); 723 } 724 } 725 } 726 727 /** 728 * Return the LoaderManager for this fragment, creating it if needed. 729 */ 730 public LoaderManager getLoaderManager() { 731 if (mLoaderManager != null) { 732 return mLoaderManager; 733 } 734 mCheckedForLoaderManager = true; 735 mLoaderManager = mActivity.getLoaderManager(mIndex, mLoadersStarted, true); 736 return mLoaderManager; 737 } 738 739 /** 740 * Call {@link Activity#startActivity(Intent)} on the fragment's 741 * containing Activity. 742 */ 743 public void startActivity(Intent intent) { 744 mActivity.startActivityFromFragment(this, intent, -1); 745 } 746 747 /** 748 * Call {@link Activity#startActivityForResult(Intent, int)} on the fragment's 749 * containing Activity. 750 */ 751 public void startActivityForResult(Intent intent, int requestCode) { 752 mActivity.startActivityFromFragment(this, intent, requestCode); 753 } 754 755 /** 756 * Receive the result from a previous call to 757 * {@link #startActivityForResult(Intent, int)}. This follows the 758 * related Activity API as described there in 759 * {@link Activity#onActivityResult(int, int, Intent)}. 760 * 761 * @param requestCode The integer request code originally supplied to 762 * startActivityForResult(), allowing you to identify who this 763 * result came from. 764 * @param resultCode The integer result code returned by the child activity 765 * through its setResult(). 766 * @param data An Intent, which can return result data to the caller 767 * (various data can be attached to Intent "extras"). 768 */ 769 public void onActivityResult(int requestCode, int resultCode, Intent data) { 770 } 771 772 /** 773 * Called when a fragment is being created as part of a view layout 774 * inflation, typically from setting the content view of an activity. This 775 * will be called immediately after the fragment is created from a <fragment> 776 * tag in a layout file. Note this is <em>before</em> the fragment's 777 * {@link #onAttach(Activity)} has been called; all you should do here is 778 * parse the attributes and save them away. A convenient thing to do is 779 * simply copy them into a Bundle that is given to {@link #setArguments(Bundle)}. 780 * 781 * <p>This is called every time the fragment is inflated, even if it is 782 * being inflated into a new instance with saved state. Because a fragment's 783 * arguments are retained across instances, it may make no sense to re-parse 784 * the attributes into new arguments. You may want to first check 785 * {@link #getArguments()} and only parse the attributes if it returns null, 786 * the assumption being that if it is non-null those are the same arguments 787 * from the first time the fragment was inflated. (That said, you may want 788 * to have layouts change for different configurations such as landscape 789 * and portrait, which can have different attributes. If so, you will need 790 * to re-parse the attributes each time this is called to generate new 791 * arguments.)</p> 792 * 793 * @param attrs The attributes at the tag where the fragment is 794 * being created. 795 * @param savedInstanceState If the fragment is being re-created from 796 * a previous saved state, this is the state. 797 */ 798 public void onInflate(AttributeSet attrs, Bundle savedInstanceState) { 799 mCalled = true; 800 } 801 802 /** 803 * Called when a fragment is first attached to its activity. 804 * {@link #onCreate(Bundle)} will be called after this. 805 */ 806 public void onAttach(Activity activity) { 807 mCalled = true; 808 } 809 810 /** 811 * Called when a fragment loads an animation. 812 */ 813 public Animator onCreateAnimator(int transit, boolean enter, int nextAnim) { 814 return null; 815 } 816 817 /** 818 * Called to do initial creation of a fragment. This is called after 819 * {@link #onAttach(Activity)} and before 820 * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}. 821 * 822 * <p>Note that this can be called while the fragment's activity is 823 * still in the process of being created. As such, you can not rely 824 * on things like the activity's content view hierarchy being initialized 825 * at this point. If you want to do work once the activity itself is 826 * created, see {@link #onActivityCreated(Bundle)}. 827 * 828 * @param savedInstanceState If the fragment is being re-created from 829 * a previous saved state, this is the state. 830 */ 831 public void onCreate(Bundle savedInstanceState) { 832 mCalled = true; 833 } 834 835 /** 836 * Called to have the fragment instantiate its user interface view. 837 * This is optional, and non-graphical fragments can return null (which 838 * is the default implementation). This will be called between 839 * {@link #onCreate(Bundle)} and {@link #onActivityCreated(Bundle)}. 840 * 841 * <p>If you return a View from here, you will later be called in 842 * {@link #onDestroyView} when the view is being released. 843 * 844 * @param inflater The LayoutInflater object that can be used to inflate 845 * any views in the fragment, 846 * @param container If non-null, this is the parent view that the fragment's 847 * UI should be attached to. The fragment should not add the view itself, 848 * but this can be used to generate the LayoutParams of the view. 849 * @param savedInstanceState If non-null, this fragment is being re-constructed 850 * from a previous saved state as given here. 851 * 852 * @return Return the View for the fragment's UI, or null. 853 */ 854 public View onCreateView(LayoutInflater inflater, ViewGroup container, 855 Bundle savedInstanceState) { 856 return null; 857 } 858 859 public View getView() { 860 return mView; 861 } 862 863 /** 864 * Called when the fragment's activity has been created and this 865 * fragment's view hierarchy instantiated. It can be used to do final 866 * initialization once these pieces are in place, such as retrieving 867 * views or restoring state. It is also useful for fragments that use 868 * {@link #setRetainInstance(boolean)} to retain their instance, 869 * as this callback tells the fragment when it is fully associated with 870 * the new activity instance. This is called after {@link #onCreateView} 871 * and before {@link #onStart()}. 872 * 873 * @param savedInstanceState If the fragment is being re-created from 874 * a previous saved state, this is the state. 875 */ 876 public void onActivityCreated(Bundle savedInstanceState) { 877 mCalled = true; 878 } 879 880 /** 881 * Called when the Fragment is visible to the user. This is generally 882 * tied to {@link Activity#onStart() Activity.onStart} of the containing 883 * Activity's lifecycle. 884 */ 885 public void onStart() { 886 mCalled = true; 887 888 if (!mLoadersStarted) { 889 mLoadersStarted = true; 890 if (!mCheckedForLoaderManager) { 891 mCheckedForLoaderManager = true; 892 mLoaderManager = mActivity.getLoaderManager(mIndex, mLoadersStarted, false); 893 } 894 if (mLoaderManager != null) { 895 mLoaderManager.doStart(); 896 } 897 } 898 } 899 900 /** 901 * Called when the fragment is visible to the user and actively running. 902 * This is generally 903 * tied to {@link Activity#onResume() Activity.onResume} of the containing 904 * Activity's lifecycle. 905 */ 906 public void onResume() { 907 mCalled = true; 908 } 909 910 /** 911 * Called to ask the fragment to save its current dynamic state, so it 912 * can later be reconstructed in a new instance of its process is 913 * restarted. If a new instance of the fragment later needs to be 914 * created, the data you place in the Bundle here will be available 915 * in the Bundle given to {@link #onCreate(Bundle)}, 916 * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}, and 917 * {@link #onActivityCreated(Bundle)}. 918 * 919 * <p>This corresponds to {@link Activity#onSaveInstanceState(Bundle) 920 * Activity.onSaveInstanceState(Bundle)} and most of the discussion there 921 * applies here as well. Note however: <em>this method may be called 922 * at any time before {@link #onDestroy()}</em>. There are many situations 923 * where a fragment may be mostly torn down (such as when placed on the 924 * back stack with no UI showing), but its state will not be saved until 925 * its owning activity actually needs to save its state. 926 * 927 * @param outState Bundle in which to place your saved state. 928 */ 929 public void onSaveInstanceState(Bundle outState) { 930 } 931 932 public void onConfigurationChanged(Configuration newConfig) { 933 mCalled = true; 934 } 935 936 /** 937 * Called when the Fragment is no longer resumed. This is generally 938 * tied to {@link Activity#onPause() Activity.onPause} of the containing 939 * Activity's lifecycle. 940 */ 941 public void onPause() { 942 mCalled = true; 943 } 944 945 /** 946 * Called when the Fragment is no longer started. This is generally 947 * tied to {@link Activity#onStop() Activity.onStop} of the containing 948 * Activity's lifecycle. 949 */ 950 public void onStop() { 951 mCalled = true; 952 } 953 954 public void onLowMemory() { 955 mCalled = true; 956 } 957 958 /** 959 * Called when the view previously created by {@link #onCreateView} has 960 * been detached from the fragment. The next time the fragment needs 961 * to be displayed, a new view will be created. This is called 962 * after {@link #onStop()} and before {@link #onDestroy()}. It is called 963 * <em>regardless</em> of whether {@link #onCreateView} returned a 964 * non-null view. Internally it is called after the view's state has 965 * been saved but before it has been removed from its parent. 966 */ 967 public void onDestroyView() { 968 mCalled = true; 969 } 970 971 /** 972 * Called when the fragment is no longer in use. This is called 973 * after {@link #onStop()} and before {@link #onDetach()}. 974 */ 975 public void onDestroy() { 976 mCalled = true; 977 //Log.v("foo", "onDestroy: mCheckedForLoaderManager=" + mCheckedForLoaderManager 978 // + " mLoaderManager=" + mLoaderManager); 979 if (!mCheckedForLoaderManager) { 980 mCheckedForLoaderManager = true; 981 mLoaderManager = mActivity.getLoaderManager(mIndex, mLoadersStarted, false); 982 } 983 if (mLoaderManager != null) { 984 mLoaderManager.doDestroy(); 985 } 986 } 987 988 /** 989 * Called when the fragment is no longer attached to its activity. This 990 * is called after {@link #onDestroy()}. 991 */ 992 public void onDetach() { 993 mCalled = true; 994 } 995 996 /** 997 * Initialize the contents of the Activity's standard options menu. You 998 * should place your menu items in to <var>menu</var>. For this method 999 * to be called, you must have first called {@link #setHasOptionsMenu}. See 1000 * {@link Activity#onCreateOptionsMenu(Menu) Activity.onCreateOptionsMenu} 1001 * for more information. 1002 * 1003 * @param menu The options menu in which you place your items. 1004 * 1005 * @see #setHasOptionsMenu 1006 * @see #onPrepareOptionsMenu 1007 * @see #onOptionsItemSelected 1008 */ 1009 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 1010 } 1011 1012 /** 1013 * Prepare the Screen's standard options menu to be displayed. This is 1014 * called right before the menu is shown, every time it is shown. You can 1015 * use this method to efficiently enable/disable items or otherwise 1016 * dynamically modify the contents. See 1017 * {@link Activity#onPrepareOptionsMenu(Menu) Activity.onPrepareOptionsMenu} 1018 * for more information. 1019 * 1020 * @param menu The options menu as last shown or first initialized by 1021 * onCreateOptionsMenu(). 1022 * 1023 * @see #setHasOptionsMenu 1024 * @see #onCreateOptionsMenu 1025 */ 1026 public void onPrepareOptionsMenu(Menu menu) { 1027 } 1028 1029 /** 1030 * This hook is called whenever an item in your options menu is selected. 1031 * The default implementation simply returns false to have the normal 1032 * processing happen (calling the item's Runnable or sending a message to 1033 * its Handler as appropriate). You can use this method for any items 1034 * for which you would like to do processing without those other 1035 * facilities. 1036 * 1037 * <p>Derived classes should call through to the base class for it to 1038 * perform the default menu handling. 1039 * 1040 * @param item The menu item that was selected. 1041 * 1042 * @return boolean Return false to allow normal menu processing to 1043 * proceed, true to consume it here. 1044 * 1045 * @see #onCreateOptionsMenu 1046 */ 1047 public boolean onOptionsItemSelected(MenuItem item) { 1048 return false; 1049 } 1050 1051 /** 1052 * This hook is called whenever the options menu is being closed (either by the user canceling 1053 * the menu with the back/menu button, or when an item is selected). 1054 * 1055 * @param menu The options menu as last shown or first initialized by 1056 * onCreateOptionsMenu(). 1057 */ 1058 public void onOptionsMenuClosed(Menu menu) { 1059 } 1060 1061 /** 1062 * Called when a context menu for the {@code view} is about to be shown. 1063 * Unlike {@link #onCreateOptionsMenu}, this will be called every 1064 * time the context menu is about to be shown and should be populated for 1065 * the view (or item inside the view for {@link AdapterView} subclasses, 1066 * this can be found in the {@code menuInfo})). 1067 * <p> 1068 * Use {@link #onContextItemSelected(android.view.MenuItem)} to know when an 1069 * item has been selected. 1070 * <p> 1071 * The default implementation calls up to 1072 * {@link Activity#onCreateContextMenu Activity.onCreateContextMenu}, though 1073 * you can not call this implementation if you don't want that behavior. 1074 * <p> 1075 * It is not safe to hold onto the context menu after this method returns. 1076 * {@inheritDoc} 1077 */ 1078 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { 1079 getActivity().onCreateContextMenu(menu, v, menuInfo); 1080 } 1081 1082 /** 1083 * Registers a context menu to be shown for the given view (multiple views 1084 * can show the context menu). This method will set the 1085 * {@link OnCreateContextMenuListener} on the view to this fragment, so 1086 * {@link #onCreateContextMenu(ContextMenu, View, ContextMenuInfo)} will be 1087 * called when it is time to show the context menu. 1088 * 1089 * @see #unregisterForContextMenu(View) 1090 * @param view The view that should show a context menu. 1091 */ 1092 public void registerForContextMenu(View view) { 1093 view.setOnCreateContextMenuListener(this); 1094 } 1095 1096 /** 1097 * Prevents a context menu to be shown for the given view. This method will 1098 * remove the {@link OnCreateContextMenuListener} on the view. 1099 * 1100 * @see #registerForContextMenu(View) 1101 * @param view The view that should stop showing a context menu. 1102 */ 1103 public void unregisterForContextMenu(View view) { 1104 view.setOnCreateContextMenuListener(null); 1105 } 1106 1107 /** 1108 * This hook is called whenever an item in a context menu is selected. The 1109 * default implementation simply returns false to have the normal processing 1110 * happen (calling the item's Runnable or sending a message to its Handler 1111 * as appropriate). You can use this method for any items for which you 1112 * would like to do processing without those other facilities. 1113 * <p> 1114 * Use {@link MenuItem#getMenuInfo()} to get extra information set by the 1115 * View that added this menu item. 1116 * <p> 1117 * Derived classes should call through to the base class for it to perform 1118 * the default menu handling. 1119 * 1120 * @param item The context menu item that was selected. 1121 * @return boolean Return false to allow normal context menu processing to 1122 * proceed, true to consume it here. 1123 */ 1124 public boolean onContextItemSelected(MenuItem item) { 1125 return false; 1126 } 1127 1128 /** 1129 * Print the Fragments's state into the given stream. 1130 * 1131 * @param prefix Text to print at the front of each line. 1132 * @param fd The raw file descriptor that the dump is being sent to. 1133 * @param writer The PrintWriter to which you should dump your state. This will be 1134 * closed for you after you return. 1135 * @param args additional arguments to the dump request. 1136 */ 1137 public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { 1138 writer.print(prefix); writer.print("mFragmentId="); writer.print(mFragmentId); 1139 writer.print(" mContainerId="); writer.print(mContainerId); 1140 writer.print(" mTag="); writer.println(mTag); 1141 writer.print(prefix); writer.print("mState="); writer.print(mState); 1142 writer.print(" mIndex="); writer.print(mIndex); 1143 writer.print(" mWho="); writer.print(mWho); 1144 writer.print(" mBackStackNesting="); writer.println(mBackStackNesting); 1145 writer.print(prefix); writer.print("mAdded="); writer.print(mAdded); 1146 writer.print(" mResumed="); writer.print(mResumed); 1147 writer.print(" mFromLayout="); writer.print(mFromLayout); 1148 writer.print(" mInLayout="); writer.println(mInLayout); 1149 writer.print(prefix); writer.print("mHidden="); writer.print(mHidden); 1150 writer.print(" mRetainInstance="); writer.print(mRetainInstance); 1151 writer.print(" mRetaining="); writer.print(mRetaining); 1152 writer.print(" mHasMenu="); writer.println(mHasMenu); 1153 if (mFragmentManager != null) { 1154 writer.print(prefix); writer.print("mFragmentManager="); 1155 writer.println(mFragmentManager); 1156 } 1157 if (mImmediateActivity != null) { 1158 writer.print(prefix); writer.print("mImmediateActivity="); 1159 writer.println(mImmediateActivity); 1160 } 1161 if (mActivity != null) { 1162 writer.print(prefix); writer.print("mActivity="); 1163 writer.println(mActivity); 1164 } 1165 if (mArguments != null) { 1166 writer.print(prefix); writer.print("mArguments="); writer.println(mArguments); 1167 } 1168 if (mSavedFragmentState != null) { 1169 writer.print(prefix); writer.print("mSavedFragmentState="); 1170 writer.println(mSavedFragmentState); 1171 } 1172 if (mSavedViewState != null) { 1173 writer.print(prefix); writer.print("mSavedViewState="); 1174 writer.println(mSavedViewState); 1175 } 1176 if (mTarget != null) { 1177 writer.print(prefix); writer.print("mTarget="); writer.print(mTarget); 1178 writer.print(" mTargetRequestCode="); 1179 writer.println(mTargetRequestCode); 1180 } 1181 if (mNextAnim != 0) { 1182 writer.print(prefix); writer.print("mNextAnim="); writer.println(mNextAnim); 1183 } 1184 if (mContainer != null) { 1185 writer.print(prefix); writer.print("mContainer="); writer.println(mContainer); 1186 } 1187 if (mView != null) { 1188 writer.print(prefix); writer.print("mView="); writer.println(mView); 1189 } 1190 if (mLoaderManager != null) { 1191 writer.print(prefix); writer.print("mLoaderManager="); writer.print(mLoaderManager); 1192 writer.print(" mLoadersStarted="); writer.print(mLoadersStarted); 1193 writer.print(" mCheckedForLoaderManager="); 1194 writer.println(mCheckedForLoaderManager); 1195 } 1196 } 1197 1198 void performStop() { 1199 onStop(); 1200 1201 if (mLoadersStarted) { 1202 mLoadersStarted = false; 1203 if (!mCheckedForLoaderManager) { 1204 mCheckedForLoaderManager = true; 1205 mLoaderManager = mActivity.getLoaderManager(mIndex, mLoadersStarted, false); 1206 } 1207 if (mLoaderManager != null) { 1208 if (mActivity == null || !mActivity.mChangingConfigurations) { 1209 mLoaderManager.doStop(); 1210 } else { 1211 mLoaderManager.doRetain(); 1212 } 1213 } 1214 } 1215 } 1216} 1217