Maybe fix #2925641: calling onCreateOptionsMenu before attached activity
Also add some APIs to PreferenceActivity.
Change-Id: I85894a3eb9cd3e5adb78b82e85454c0d74773178
diff --git a/api/current.xml b/api/current.xml
index dd39281..09050ec 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -138764,6 +138764,17 @@
visibility="public"
>
</method>
+<method name="hasHeaders"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="invalidateHeaders"
return="void"
abstract="false"
@@ -138775,6 +138786,17 @@
visibility="public"
>
</method>
+<method name="isMultiPane"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="loadHeadersFromResource"
return="void"
abstract="false"
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index d40d7d8..bf660ea9 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -56,7 +56,6 @@
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.ContextThemeWrapper;
-import android.view.InflateException;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -114,6 +113,7 @@
*
* <p>Topics covered here:
* <ol>
+ * <li><a href="#Fragments">Fragments</a>
* <li><a href="#ActivityLifecycle">Activity Lifecycle</a>
* <li><a href="#ConfigurationChanges">Configuration Changes</a>
* <li><a href="#StartingActivities">Starting Activities and Getting Results</a>
@@ -122,6 +122,14 @@
* <li><a href="#ProcessLifecycle">Process Lifecycle</a>
* </ol>
*
+ * <a name="Fragments"></a>
+ * <h3>Fragments</h3>
+ *
+ * <p>Starting with {@link android.os.Build.VERSION_CODES#HONEYCOMB}, Activity
+ * implementations can make use of the {@link Fragment} class to better
+ * modularize their code, build more sophisticated user interfaces for larger
+ * screens, and help scale their application between small and large screens.
+ *
* <a name="ActivityLifecycle"></a>
* <h3>Activity Lifecycle</h3>
*
@@ -1485,6 +1493,11 @@
* {@link #getLastNonConfigurationInstance()} in the new activity
* instance.
*
+ * <em>If you are targeting {@link android.os.Build.VERSION_CODES#HONEYCOMB}
+ * or later, consider instead using a {@link Fragment} with
+ * {@link Fragment#setRetainInstance(boolean)
+ * Fragment.setRetainInstance(boolean}.</em>
+ *
* <p>This function is called purely as an optimization, and you must
* not rely on it being called. When it is called, a number of guarantees
* will be made to help optimize configuration switching:
@@ -1623,6 +1636,10 @@
* {@link #startManagingCursor} so that the activity will manage its
* lifecycle for you.
*
+ * <em>If you are targeting {@link android.os.Build.VERSION_CODES#HONEYCOMB}
+ * or later, consider instead using {@link LoaderManager} instead, available
+ * via {@link #getLoaderManager()}.</em>
+ *
* @param uri The URI of the content provider to query.
* @param projection List of columns to return.
* @param selection SQL WHERE clause.
@@ -1634,11 +1651,8 @@
* @see #startManagingCursor
* @hide
*/
- public final Cursor managedQuery(Uri uri,
- String[] projection,
- String selection,
- String sortOrder)
- {
+ public final Cursor managedQuery(Uri uri, String[] projection, String selection,
+ String sortOrder) {
Cursor c = getContentResolver().query(uri, projection, selection, null, sortOrder);
if (c != null) {
startManagingCursor(c);
@@ -1653,6 +1667,10 @@
* {@link #startManagingCursor} so that the activity will manage its
* lifecycle for you.
*
+ * <em>If you are targeting {@link android.os.Build.VERSION_CODES#HONEYCOMB}
+ * or later, consider instead using {@link LoaderManager} instead, available
+ * via {@link #getLoaderManager()}.</em>
+ *
* @param uri The URI of the content provider to query.
* @param projection List of columns to return.
* @param selection SQL WHERE clause.
@@ -1664,12 +1682,8 @@
* @see ContentResolver#query(android.net.Uri , String[], String, String[], String)
* @see #startManagingCursor
*/
- public final Cursor managedQuery(Uri uri,
- String[] projection,
- String selection,
- String[] selectionArgs,
- String sortOrder)
- {
+ public final Cursor managedQuery(Uri uri, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder) {
Cursor c = getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);
if (c != null) {
startManagingCursor(c);
@@ -1685,6 +1699,10 @@
* it will call {@link Cursor#requery} for you. When the activity is
* destroyed, all managed Cursors will be closed automatically.
*
+ * <em>If you are targeting {@link android.os.Build.VERSION_CODES#HONEYCOMB}
+ * or later, consider instead using {@link LoaderManager} instead, available
+ * via {@link #getLoaderManager()}.</em>
+ *
* @param c The Cursor to be managed.
*
* @see #managedQuery(android.net.Uri , String[], String, String[], String)
@@ -2689,6 +2707,9 @@
* by the activity. The default implementation calls through to
* {@link #onCreateDialog(int)} for compatibility.
*
+ * <em>If you are targeting {@link android.os.Build.VERSION_CODES#HONEYCOMB}
+ * or later, consider instead using a {@link DialogFragment} instead.</em>
+ *
* <p>If you use {@link #showDialog(int)}, the activity will call through to
* this method the first time, and hang onto it thereafter. Any dialog
* that is created by this method will automatically be saved and restored
@@ -2761,6 +2782,9 @@
* will be made with the same id the first time this is called for a given
* id. From thereafter, the dialog will be automatically saved and restored.
*
+ * <em>If you are targeting {@link android.os.Build.VERSION_CODES#HONEYCOMB}
+ * or later, consider instead using a {@link DialogFragment} instead.</em>
+ *
* <p>Each time a dialog is shown, {@link #onPrepareDialog(int, Dialog, Bundle)} will
* be made to provide an opportunity to do any timely preparation.
*
@@ -4309,6 +4333,7 @@
}
final void performDestroy() {
+ mWindow.destroy();
mFragments.dispatchDestroy();
onDestroy();
if (mLoaderManager != null) {
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 6a1d527..b10a8a8 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -129,7 +129,152 @@
/**
* A Fragment is a piece of an application's user interface or behavior
- * that can be placed in an {@link Activity}.
+ * that can be placed in an {@link Activity}. Interaction with fragments
+ * is done through {@link FragmentManager}, which can be obtained via
+ * {@link Activity#getFragmentManager() Activity.getFragmentManager()} and
+ * {@link Fragment#getFragmentManager() Fragment.getFragmentManager()}.
+ *
+ * <p>The Fragment class can be used many ways to achieve a wide variety of
+ * results. It is core, it represents a particular operation or interface
+ * that is running within a larger {@link Activity}. A Fragment is closely
+ * tied to the Activity it is in, and can not be used apart from one. Though
+ * Fragment defines its own lifecycle, that lifecycle is dependent on its
+ * activity: if the activity is stopped, no fragments inside of it can be
+ * started; when the activity is destroyed, all fragments will be destroyed.
+ *
+ * <p>All subclasses of Fragment must include a public empty constructor.
+ * The framework will often re-instantiate a fragment class when needed,
+ * in particular during state restore, and needs to be able to find this
+ * constructor to instantiate it. If the empty constructor is not available,
+ * a runtime exception will occur in some cases during state restore.
+ *
+ * <p>Topics covered here:
+ * <ol>
+ * <li><a href="#Lifecycle">Lifecycle</a>
+ * <li><a href="#Layout">Layout</a>
+ * <li><a href="#BackStack">Back Stack</a>
+ * </ol>
+ *
+ * <a name="Lifecycle"></a>
+ * <h3>Lifecycle</h3>
+ *
+ * <p>Though a Fragment's lifecycle is tied to its owning activity, it has
+ * its own wrinkle on the standard activity lifecycle. It includes basic
+ * activity lifecycle methods such as {@link #onResume}, but also important
+ * are methods related to interactions with the activity and UI generation.
+ *
+ * <p>The core series of lifecycle methods that are called to bring a fragment
+ * up to resumed state (interacting with the user) are:
+ *
+ * <ol>
+ * <li> {@link #onAttach} called once the fragment is associated with its activity.
+ * <li> {@link #onCreate} called to do initial creation of the fragment.
+ * <li> {@link #onCreateView} creates and returns the view hierarchy associated
+ * with the fragment.
+ * <li> {@link #onActivityCreated} tells the fragment that its activity has
+ * completed its own {@link Activity#onCreate Activity.onCreaate}.
+ * <li> {@link #onStart} makes the fragment visible to the user (based on its
+ * containing activity being started).
+ * <li> {@link #onResume} makes the fragment interacting with the user (based on its
+ * containing activity being resumed).
+ * </ol>
+ *
+ * <p>As a fragment is no longer being used, it goes through a reverse
+ * series of callbacks:
+ *
+ * <ol>
+ * <li> {@link #onPause} fragment is no longer interacting with the user either
+ * because its activity is being paused or a fragment operation is modifying it
+ * in the activity.
+ * <li> {@link #onStop} fragment is no longer visible to the user either
+ * because its activity is being stopped or a fragment operation is modifying it
+ * in the activity.
+ * <li> {@link #onDestroyView} allows the fragment to clean up resources
+ * associated with its View.
+ * <li> {@link #onDestroy} called to do final cleanup of the fragment's state.
+ * <li> {@link #onDetach} called immediately prior to the fragment no longer
+ * being associated with its activity.
+ * </ol>
+ *
+ * <a name="Layout"></a>
+ * <h3>Layout</h3>
+ *
+ * <p>Fragments can be used as part of your application's layout, allowing
+ * you to better modularize your code and more easily adjust your user
+ * interface to the screen it is running on. As an example, we can look
+ * at a simple program consisting of a list of items, and display of the
+ * details of each item.</p>
+ *
+ * <p>An activity's layout XML can include <code><fragment></code> tags
+ * to embed fragment instances inside of the layout. For example, here is
+ * a simply layout that embeds one fragment:</p>
+ *
+ * {@sample development/samples/ApiDemos/res/layout/fragment_layout.xml layout}
+ *
+ * <p>The layout is installed in the activity in the normal way:</p>
+ *
+ * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java
+ * main}
+ *
+ * <p>The titles fragment, showing a list of titles, is very simple, relying
+ * on {@link ListFragment} for most of its work. Note the implementation of
+ * clicking an item, which can either update
+ * the content of the details fragment or start a new activity show the
+ * details depending on whether the current activity's layout can show the
+ * details.</p>
+ *
+ * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java
+ * titles}
+ *
+ * <p>The details fragment showing the contents of selected item here just
+ * displays a string of text based on an index of a string array built in to
+ * the app:</p>
+ *
+ * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java
+ * details}
+ *
+ * <p>In this case when the user clicks on a title, there is no details
+ * fragment in the current activity, so the title title fragment's click code will
+ * launch a new activity to display the details fragment:</p>
+ *
+ * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java
+ * details_activity}
+ *
+ * <p>However the screen may be large enough to show both the list of titles
+ * and details about the currently selected title. To use such a layout on
+ * a landscape screen, this alternative layout can be placed under layout-land:</p>
+ *
+ * {@sample development/samples/ApiDemos/res/layout-land/fragment_layout.xml layout}
+ *
+ * <p>Note how the prior code will adjust to this alternative UI flow: the
+ * titles fragment will now show its text inside of its activity, and the
+ * details activity will finish of it finds itself running in a configuration
+ * where the details can be shown inline.
+ *
+ * <a name="BackStack"></a>
+ * <h3>Back Stack</h3>
+ *
+ * <p>The transaction in which fragments are modified can be placed on an
+ * internal back-stack of the owning activity. When the user presses back
+ * in the activity, any transactions on the back stack are popped off before
+ * the activity itself is finished.
+ *
+ * <p>For example, consider this simple fragment that is instantiated with
+ * an integer argument and displays that in a TextView in its UI:</p>
+ *
+ * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentStack.java
+ * fragment}
+ *
+ * <p>A function that creates a new instance of the fragment, replacing
+ * whatever current fragment instance is being shown and pushing that change
+ * on to the back stack could be written as:
+ *
+ * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentStack.java
+ * add_stack}
+ *
+ * <p>After each call to this function, a new entry is on the stack, and
+ * pressing back will pop it to return the user to whatever previous state
+ * the activity UI was in.
*/
public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener {
private static final HashMap<String, Class<?>> sClassMap =
@@ -235,7 +380,7 @@
}
/**
- * Default constructor. <strong>Every</string> fragment must have an
+ * Default constructor. <strong>Every</strong> fragment must have an
* empty constructor, so it can be instantiated when restoring its
* activity's state. It is strongly recommended that subclasses do not
* have other constructors with parameters, since these constructors
@@ -243,10 +388,13 @@
* arguments can be supplied by the caller with {@link #setArguments}
* and later retrieved by the Fragment with {@link #getArguments}.
*
- * <p>The first place where application code should generally run is in
- * {@link #onAttach(Activity)}, which is the point where the fragment is
- * actually attached to its activity and thus capable of doing most
- * retrieve such parameters from the activity in {@link #onAttach(Activity)}.
+ * <p>Applications should generally not implement a constructor. The
+ * first place application code an run where the fragment is ready to
+ * be used is in {@link #onAttach(Activity)}, the point where the fragment
+ * is actually associated with its activity. Some applications may also
+ * want to implement {@link #onInflate} to retrieve attributes from a
+ * layout resource, though should take care here because this happens for
+ * the fragment is attached to its activity.
*/
public Fragment() {
}
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index 03fc399..70a2b80 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -393,6 +393,22 @@
}
/**
+ * Returns true if this activity is currently showing the header list.
+ */
+ public boolean hasHeaders() {
+ return getListView().getVisibility() == View.VISIBLE
+ && mPreferenceManager == null;
+ }
+
+ /**
+ * Returns true if this activity is showing multiple panes -- the headers
+ * and a preference fragment.
+ */
+ public boolean isMultiPane() {
+ return hasHeaders() && mPrefsContainer.getVisibility() == View.VISIBLE;
+ }
+
+ /**
* Called to determine if the activity should run in multi-pane mode.
* The default implementation returns true if the screen is large
* enough.
@@ -408,9 +424,11 @@
}
/**
- * Called to determine whether the header list should be hidden. The
- * default implementation hides the list if the activity is being re-launched
- * when not in multi-pane mode.
+ * Called to determine whether the header list should be hidden.
+ * The default implementation returns the
+ * value given in {@link #EXTRA_NO_HEADERS} or false if it is not supplied.
+ * This is set to false, for example, when the activity is being re-launched
+ * to show a particular preference activity.
*/
public boolean onIsHidingHeaders() {
return getIntent().getBooleanExtra(EXTRA_NO_HEADERS, false);
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 36f6bb2..705af0f 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -130,6 +130,8 @@
private boolean mHasSoftInputMode = false;
+ private boolean mDestroyed;
+
// The current window attributes.
private final WindowManager.LayoutParams mWindowAttributes =
new WindowManager.LayoutParams();
@@ -382,6 +384,16 @@
return mHasChildren;
}
+ /** @hide */
+ public final void destroy() {
+ mDestroyed = true;
+ }
+
+ /** @hide */
+ public final boolean isDestroyed() {
+ return mDestroyed;
+ }
+
/**
* Set the window manager for use by this Window to, for example,
* display panels. This is <em>not</em> used for displaying the
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 6be5546..f59f32c 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -2459,7 +2459,9 @@
// being called in the middle of onCreate or similar.
mDecor.post(new Runnable() {
public void run() {
- invalidatePanelMenu(FEATURE_ACTION_BAR);
+ if (!isDestroyed()) {
+ invalidatePanelMenu(FEATURE_ACTION_BAR);
+ }
}
});
}