diff --git a/api/current.xml b/api/current.xml index 3535ffc58a4fa..b0056d7f22243 100644 --- a/api/current.xml +++ b/api/current.xml @@ -21946,6 +21946,17 @@ visibility="public" > + + - - - - - - + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + @@ -179210,6 +179474,18 @@ deprecated="not deprecated" visibility="public" > + + + + + + diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index d7bab1bc80806..ec3cbc3729c4c 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -667,7 +667,7 @@ public class Activity extends ContextThemeWrapper private CharSequence mTitle; private int mTitleColor = 0; - final FragmentManager mFragments = new FragmentManager(); + final FragmentManagerImpl mFragments = new FragmentManagerImpl(); SparseArray mAllLoaderManagers; LoaderManagerImpl mLoaderManager; @@ -1579,12 +1579,20 @@ public class Activity extends ContextThemeWrapper mCalled = true; } + /** + * Return the FragmentManager for interacting with fragments associated + * with this activity. + */ + public FragmentManager getFragmentManager() { + return mFragments; + } + /** * Start a series of edit operations on the Fragments associated with * this activity. */ public FragmentTransaction openFragmentTransaction() { - return new BackStackEntry(mFragments); + return mFragments.openTransaction(); } void invalidateFragmentIndex(int index) { @@ -2072,7 +2080,7 @@ public class Activity extends ContextThemeWrapper * to pop, else false. */ public boolean popBackStack() { - return popBackStack(null, 0); + return mFragments.popBackStack(); } /** @@ -2085,7 +2093,7 @@ public class Activity extends ContextThemeWrapper * @param flags Either 0 or {@link #POP_BACK_STACK_INCLUSIVE}. */ public boolean popBackStack(String name, int flags) { - return mFragments.popBackStackState(mHandler, name, flags); + return mFragments.popBackStack(name, flags); } /** @@ -2099,7 +2107,7 @@ public class Activity extends ContextThemeWrapper * @param flags Either 0 or {@link #POP_BACK_STACK_INCLUSIVE}. */ public boolean popBackStack(int id, int flags) { - return mFragments.popBackStackState(mHandler, id, flags); + return mFragments.popBackStack(id, flags); } /** @@ -3999,43 +4007,36 @@ public class Activity extends ContextThemeWrapper + ": Must specify unique android:id for " + fname); } - try { - // If we restored from a previous state, we may already have - // instantiated this fragment from the state and should use - // that instance instead of making a new one. - Fragment fragment = mFragments.findFragmentById(id); - if (FragmentManager.DEBUG) Log.v(TAG, "onCreateView: id=0x" - + Integer.toHexString(id) + " fname=" + fname - + " existing=" + fragment); - if (fragment == null) { - fragment = Fragment.instantiate(this, fname); - fragment.mFromLayout = true; - fragment.mFragmentId = id; - fragment.mTag = tag; - fragment.mImmediateActivity = this; - mFragments.addFragment(fragment, true); - } - // If this fragment is newly instantiated (either right now, or - // from last saved state), then give it the attributes to - // initialize itself. - if (!fragment.mRetaining) { - fragment.onInflate(this, attrs, fragment.mSavedFragmentState); - } - if (fragment.mView == null) { - throw new IllegalStateException("Fragment " + fname - + " did not create a view."); - } - fragment.mView.setId(id); - if (fragment.mView.getTag() == null) { - fragment.mView.setTag(tag); - } - return fragment.mView; - } catch (Exception e) { - InflateException ie = new InflateException(attrs.getPositionDescription() - + ": Error inflating fragment " + fname); - ie.initCause(e); - throw ie; + // If we restored from a previous state, we may already have + // instantiated this fragment from the state and should use + // that instance instead of making a new one. + Fragment fragment = mFragments.findFragmentById(id); + if (FragmentManagerImpl.DEBUG) Log.v(TAG, "onCreateView: id=0x" + + Integer.toHexString(id) + " fname=" + fname + + " existing=" + fragment); + if (fragment == null) { + fragment = Fragment.instantiate(this, fname); + fragment.mFromLayout = true; + fragment.mFragmentId = id; + fragment.mTag = tag; + fragment.mImmediateActivity = this; + mFragments.addFragment(fragment, true); } + // If this fragment is newly instantiated (either right now, or + // from last saved state), then give it the attributes to + // initialize itself. + if (!fragment.mRetaining) { + fragment.onInflate(this, attrs, fragment.mSavedFragmentState); + } + if (fragment.mView == null) { + throw new IllegalStateException("Fragment " + fname + + " did not create a view."); + } + fragment.mView.setId(id); + if (fragment.mView.getTag() == null) { + fragment.mView.setTag(tag); + } + return fragment.mView; } /** diff --git a/core/java/android/app/BackStackEntry.java b/core/java/android/app/BackStackEntry.java index d63b862ac3d87..520e4fd586dd3 100644 --- a/core/java/android/app/BackStackEntry.java +++ b/core/java/android/app/BackStackEntry.java @@ -29,7 +29,7 @@ final class BackStackState implements Parcelable { final String mName; final int mIndex; - public BackStackState(FragmentManager fm, BackStackEntry bse) { + public BackStackState(FragmentManagerImpl fm, BackStackEntry bse) { int numRemoved = 0; BackStackEntry.Op op = bse.mHead; while (op != null) { @@ -38,6 +38,10 @@ final class BackStackState implements Parcelable { } mOps = new int[bse.mNumOp*5 + numRemoved]; + if (!bse.mAddToBackStack) { + throw new IllegalStateException("Not on back stack"); + } + op = bse.mHead; int pos = 0; while (op != null) { @@ -70,14 +74,15 @@ final class BackStackState implements Parcelable { mIndex = in.readInt(); } - public BackStackEntry instantiate(FragmentManager fm) { + public BackStackEntry instantiate(FragmentManagerImpl fm) { BackStackEntry bse = new BackStackEntry(fm); int pos = 0; while (pos < mOps.length) { BackStackEntry.Op op = new BackStackEntry.Op(); op.cmd = mOps[pos++]; + if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG, + "BSE " + bse + " set base fragment #" + mOps[pos]); Fragment f = fm.mActive.get(mOps[pos++]); - f.mBackStackNesting++; op.fragment = f; op.enterAnim = mOps[pos++]; op.exitAnim = mOps[pos++]; @@ -85,7 +90,10 @@ final class BackStackState implements Parcelable { if (N > 0) { op.removed = new ArrayList(N); for (int i=0; i=0; i--) { + Fragment r = op.removed.get(i); + r.mBackStackNesting += amt; + if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting of " + + r + " to " + r.mBackStackNesting); + } + } + op = op.next; + } + } + public int commit() { if (mCommitted) throw new IllegalStateException("commit already called"); - if (FragmentManager.DEBUG) Log.v(TAG, "Commit: " + this); + if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Commit: " + this); mCommitted = true; if (mAddToBackStack) { mIndex = mManager.allocBackStackIndex(this); @@ -309,7 +342,7 @@ final class BackStackEntry implements FragmentTransaction, Runnable { } public void run() { - if (FragmentManager.DEBUG) Log.v(TAG, "Run: " + this); + if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Run: " + this); if (mAddToBackStack) { if (mIndex < 0) { @@ -317,14 +350,13 @@ final class BackStackEntry implements FragmentTransaction, Runnable { } } + bumpBackStackNesting(1); + Op op = mHead; while (op != null) { switch (op.cmd) { case OP_ADD: { Fragment f = op.fragment; - if (mAddToBackStack) { - f.mBackStackNesting++; - } f.mNextAnim = op.enterAnim; mManager.addFragment(f, false); } break; @@ -333,48 +365,38 @@ final class BackStackEntry implements FragmentTransaction, Runnable { if (mManager.mAdded != null) { for (int i=0; iEvery 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 * will not be called when the fragment is re-instantiated; instead, + * arguments can be supplied by the caller with {@link #setArguments} + * and later retrieved by the Fragment with {@link #getArguments}. + * + *

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)}. */ public Fragment() { } + /** + * Like {@link #instantiate(Context, String, Bundle)} but with a null + * argument Bundle. + */ + public static Fragment instantiate(Context context, String fname) { + return instantiate(context, fname, null); + } + /** * Create a new instance of a Fragment with the given class name. This is * the same as calling its empty constructor. @@ -237,29 +264,40 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener * @param context The calling context being used to instantiate the fragment. * This is currently just used to get its ClassLoader. * @param fname The class name of the fragment to instantiate. + * @param args Bundle of arguments to supply to the fragment, which it + * can retrieve with {@link #getArguments()}. May be null. * @return Returns a new fragment instance. - * @throws NoSuchMethodException The fragment does not have an empty constructor. - * @throws ClassNotFoundException The fragment class does not exist. - * @throws IllegalArgumentException Bad arguments supplied to fragment class - * constructor (should not happen). - * @throws InstantiationException Caller does not have permission to instantiate - * the fragment (for example its constructor is not public). - * @throws IllegalAccessException Caller does not have permission to access - * the given fragment class. - * @throws InvocationTargetException Failure running the fragment's constructor. + * @throws InstantiationException If there is a failure in instantiating + * the given fragment class. This is a runtime exception; it is not + * normally expected to happen. */ - public static Fragment instantiate(Context context, String fname) - throws NoSuchMethodException, ClassNotFoundException, - IllegalArgumentException, InstantiationException, - IllegalAccessException, InvocationTargetException { - Class clazz = sClassMap.get(fname); - - if (clazz == null) { - // Class not found in the cache, see if it's real, and try to add it - clazz = context.getClassLoader().loadClass(fname); - sClassMap.put(fname, clazz); + public static Fragment instantiate(Context context, String fname, Bundle args) { + try { + Class clazz = sClassMap.get(fname); + if (clazz == null) { + // Class not found in the cache, see if it's real, and try to add it + clazz = context.getClassLoader().loadClass(fname); + sClassMap.put(fname, clazz); + } + Fragment f = (Fragment)clazz.newInstance(); + if (args != null) { + args.setClassLoader(f.getClass().getClassLoader()); + f.mArguments = args; + } + return f; + } catch (ClassNotFoundException e) { + throw new InstantiationException("Unable to instantiate fragment " + fname + + ": make sure class name exists, is public, and has an" + + " empty constructor that is public", e); + } catch (java.lang.InstantiationException e) { + throw new InstantiationException("Unable to instantiate fragment " + fname + + ": make sure class name exists, is public, and has an" + + " empty constructor that is public", e); + } catch (IllegalAccessException e) { + throw new InstantiationException("Unable to instantiate fragment " + fname + + ": make sure class name exists, is public, and has an" + + " empty constructor that is public", e); } - return (Fragment)clazz.newInstance(); } void restoreViewState() { @@ -330,6 +368,28 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener return mTag; } + /** + * Supply the construction arguments for this fragment. This can only + * be called before the fragment has been attached to its activity; that + * is, you should call it immediately after constructing the fragment. The + * arguments supplied here will be retained across fragment destroy and + * creation. + */ + final public void setArguments(Bundle args) { + if (mIndex >= 0) { + throw new IllegalStateException("Fragment already active"); + } + mArguments = args; + } + + /** + * Return the arguments supplied when the fragment was instantiated, + * if any. + */ + final public Bundle getArguments() { + return mArguments; + } + /** * Return the Activity this fragment is currently associated with. */ @@ -337,6 +397,14 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener return mActivity; } + /** + * Return the FragmentManager for interacting with fragments associated + * with this fragment's activity. + */ + final public FragmentManager getFragmentManager() { + return mActivity.mFragments; + } + /** * Return true if the fragment is currently added to its activity. */ diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index 54e37b0df5738..0556f0592d1e0 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -35,6 +35,100 @@ import android.view.animation.AnimationUtils; import java.util.ArrayList; +/** + * Interface for interacting with {@link Fragment} objects inside of an + * {@link Activity} + */ +public interface FragmentManager { + /** + * Start a series of edit operations on the Fragments associated with + * this FragmentManager. + */ + public FragmentTransaction openTransaction(); + + /** + * Finds a fragment that was identified by the given id either when inflated + * from XML or as the container ID when added in a transaction. This first + * searches through fragments that are currently added to the manager's + * activity; if no such fragment is found, then all fragments currently + * on the back stack associated with this ID are searched. + * @return The fragment if found or null otherwise. + */ + public Fragment findFragmentById(int id); + + /** + * Finds a fragment that was identified by the given tag either when inflated + * from XML or as supplied when added in a transaction. This first + * searches through fragments that are currently added to the manager's + * activity; if no such fragment is found, then all fragments currently + * on the back stack are searched. + * @return The fragment if found or null otherwise. + */ + public Fragment findFragmentByTag(String tag); + + /** + * Flag for {@link #popBackStack(String, int)} + * and {@link #popBackStack(int, int)}: If set, and the name or ID of + * a back stack entry has been supplied, then all matching entries will + * be consumed until one that doesn't match is found or the bottom of + * the stack is reached. Otherwise, all entries up to but not including that entry + * will be removed. + */ + public static final int POP_BACK_STACK_INCLUSIVE = 1<<0; + + /** + * Pop the top state off the back stack. Returns true if there was one + * to pop, else false. + */ + public boolean popBackStack(); + + /** + * Pop the last fragment transition from the manager's fragment + * back stack. If there is nothing to pop, false is returned. + * @param name If non-null, this is the name of a previous back state + * to look for; if found, all states up to that state will be popped. The + * {@link #POP_BACK_STACK_INCLUSIVE} flag can be used to control whether + * the named state itself is popped. If null, only the top state is popped. + * @param flags Either 0 or {@link #POP_BACK_STACK_INCLUSIVE}. + */ + public boolean popBackStack(String name, int flags); + + /** + * Pop all back stack states up to the one with the given identifier. + * @param id Identifier of the stated to be popped. If no identifier exists, + * false is returned. + * The identifier is the number returned by + * {@link FragmentTransaction#commit() FragmentTransaction.commit()}. The + * {@link #POP_BACK_STACK_INCLUSIVE} flag can be used to control whether + * the named state itself is popped. + * @param flags Either 0 or {@link #POP_BACK_STACK_INCLUSIVE}. + */ + public boolean popBackStack(int id, int flags); + + /** + * Put a reference to a fragment in a Bundle. This Bundle can be + * persisted as saved state, and when later restoring + * {@link #getFragment(Bundle, String)} will return the current + * instance of the same fragment. + * + * @param bundle The bundle in which to put the fragment reference. + * @param key The name of the entry in the bundle. + * @param fragment The Fragment whose reference is to be stored. + */ + public void putFragment(Bundle bundle, String key, Fragment fragment); + + /** + * Retrieve the current Fragment instance for a reference previously + * placed with {@link #putFragment(Bundle, String, Fragment)}. + * + * @param bundle The bundle from which to retrieve the fragment reference. + * @param key The name of the entry in the bundle. + * @return Returns the current Fragment instance that is associated with + * the given reference. + */ + public Fragment getFragment(Bundle bundle, String key); +} + final class FragmentManagerState implements Parcelable { FragmentState[] mActive; int[] mAdded; @@ -75,7 +169,7 @@ final class FragmentManagerState implements Parcelable { * @hide * Container for fragments associated with an activity. */ -public class FragmentManager { +class FragmentManagerImpl implements FragmentManager { static final boolean DEBUG = true; static final String TAG = "FragmentManager"; @@ -108,6 +202,47 @@ public class FragmentManager { } }; + public FragmentTransaction openTransaction() { + return new BackStackEntry(this); + } + + public boolean popBackStack() { + return popBackStackState(mActivity.mHandler, null, -1, 0); + } + + public boolean popBackStack(String name, int flags) { + return popBackStackState(mActivity.mHandler, name, -1, flags); + } + + public boolean popBackStack(int id, int flags) { + if (id < 0) { + throw new IllegalArgumentException("Bad id: " + id); + } + return popBackStackState(mActivity.mHandler, null, id, flags); + } + + public void putFragment(Bundle bundle, String key, Fragment fragment) { + if (fragment.mIndex < 0) { + throw new IllegalStateException("Fragment " + fragment + + " is not currently in the FragmentManager"); + } + bundle.putInt(key, fragment.mIndex); + } + + public Fragment getFragment(Bundle bundle, String key) { + int index = bundle.getInt(key); + if (index >= mActive.size()) { + throw new IllegalStateException("Fragement no longer exists for key " + + key + ": index " + index); + } + Fragment f = mActive.get(index); + if (f == null) { + throw new IllegalStateException("Fragement no longer exists for key " + + key + ": index " + index); + } + return f; + } + Animatable loadAnimatable(Fragment fragment, int transit, boolean enter, int transitionStyle) { Animatable animObj = fragment.onCreateAnimatable(transit, enter, @@ -387,6 +522,7 @@ public class FragmentManager { return; } + if (DEBUG) Log.v(TAG, "Freeing fragment index " + f.mIndex); mActive.set(f.mIndex, null); if (mAvailIndices == null) { mAvailIndices = new ArrayList(); @@ -636,17 +772,6 @@ public class FragmentManager { mBackStack.add(state); } - public boolean popBackStackState(Handler handler, String name, int flags) { - return popBackStackState(handler, name, -1, flags); - } - - public boolean popBackStackState(Handler handler, int id, int flags) { - if (id < 0) { - return false; - } - return popBackStackState(handler, null, id, flags); - } - boolean popBackStackState(Handler handler, String name, int id, int flags) { if (mBackStack == null) { return false; @@ -787,10 +912,13 @@ public class FragmentManager { } } + if (DEBUG) Log.v(TAG, "Saved state of " + f + ": " + + fs.mSavedFragmentState); } } if (!haveFragments) { + if (DEBUG) Log.v(TAG, "saveAllState: no fragments!"); return null; } @@ -803,6 +931,8 @@ public class FragmentManager { added = new int[N]; for (int i=0; i(); } + if (DEBUG) Log.v(TAG, "restoreAllState: adding avail #" + i); mAvailIndices.add(i); } } @@ -878,6 +1015,7 @@ public class FragmentManager { } f.mAdded = true; f.mImmediateActivity = mActivity; + if (DEBUG) Log.v(TAG, "restoreAllState: making added #" + i + ": " + f); mAdded.add(f); } } else { @@ -889,6 +1027,8 @@ public class FragmentManager { mBackStack = new ArrayList(fms.mBackStack.length); for (int i=0; i= 0) { setBackStackIndex(bse.mIndex, bse); diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java index 114f67dc7a831..ec2ca57bca12e 100644 --- a/core/java/android/preference/PreferenceActivity.java +++ b/core/java/android/preference/PreferenceActivity.java @@ -113,9 +113,28 @@ public abstract class PreferenceActivity extends ListActivity implements private static final String PREFERENCES_TAG = "android:preferences"; - private static final String EXTRA_PREFS_SHOW_FRAGMENT = ":android:show_fragment"; + /** + * When starting this activity, the invoking Intent can contain this extra + * string to specify which fragment should be initially displayed. + */ + public static final String EXTRA_SHOW_FRAGMENT = ":android:show_fragment"; - private static final String EXTRA_PREFS_NO_HEADERS = ":android:no_headers"; + /** + * When starting this activity and using {@link #EXTRA_SHOW_FRAGMENT}, + * this extra can also be specify to supply a Bundle of arguments to pass + * to that fragment when it is instantiated during the initial creation + * of PreferenceActivity. + */ + public static final String EXTRA_SHOW_FRAGMENT_ARGUMENTS = ":android:show_fragment_args"; + + /** + * When starting this activity, the invoking Intent can contain this extra + * boolean that the header list should not be displayed. This is most often + * used in conjunction with {@link #EXTRA_SHOW_FRAGMENT} to launch + * the activity to display a specific fragment that the user has navigated + * to. + */ + public static final String EXTRA_NO_HEADERS = ":android:no_headers"; private static final String BACK_STACK_PREFS = ":android:prefs"; @@ -159,14 +178,18 @@ public abstract class PreferenceActivity extends ListActivity implements private static final int FIRST_REQUEST_CODE = 100; private static final int MSG_BIND_PREFERENCES = 0; + private static final int MSG_BUILD_HEADERS = 1; private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { - case MSG_BIND_PREFERENCES: bindPreferences(); break; + case MSG_BUILD_HEADERS: + onBuildHeaders(mHeaders); + mAdapter.notifyDataSetChanged(); + break; } } }; @@ -250,6 +273,12 @@ public abstract class PreferenceActivity extends ListActivity implements * @attr ref android.R.styleable#PreferenceHeader_fragment */ String fragment; + + /** + * Optional arguments to supply to the fragment when it is + * instantiated. + */ + Bundle fragmentArguments; } @Override @@ -261,7 +290,8 @@ public abstract class PreferenceActivity extends ListActivity implements mPrefsContainer = findViewById(com.android.internal.R.id.prefs); boolean hidingHeaders = onIsHidingHeaders(); mSinglePane = hidingHeaders || !onIsMultiPane(); - String initialFragment = getIntent().getStringExtra(EXTRA_PREFS_SHOW_FRAGMENT); + String initialFragment = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT); + Bundle initialArguments = getIntent().getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS); if (initialFragment != null && mSinglePane) { // If we are just showing a fragment, we want to run in @@ -269,7 +299,7 @@ public abstract class PreferenceActivity extends ListActivity implements // the headers. getListView().setVisibility(View.GONE); mPrefsContainer.setVisibility(View.VISIBLE); - switchToHeader(initialFragment); + switchToHeader(initialFragment, initialArguments); } else { // We need to try to build the headers. @@ -283,8 +313,12 @@ public abstract class PreferenceActivity extends ListActivity implements setListAdapter(mAdapter); if (!mSinglePane) { mPrefsContainer.setVisibility(View.VISIBLE); - switchToHeader(initialFragment != null - ? initialFragment : onGetInitialFragment()); + if (initialFragment != null) { + Header h = onGetInitialHeader(); + initialFragment = h.fragment; + initialArguments = h.fragmentArguments; + } + switchToHeader(initialFragment, initialArguments); } // If there are no headers, we are in the old "just show a screen @@ -371,15 +405,18 @@ public abstract class PreferenceActivity extends ListActivity implements * when not in multi-pane mode. */ public boolean onIsHidingHeaders() { - return getIntent().getBooleanExtra(EXTRA_PREFS_NO_HEADERS, false); + return getIntent().getBooleanExtra(EXTRA_NO_HEADERS, false); } /** - * Called to determine the initial fragment to be shown. The default - * implementation simply returns the fragment of the first header. + * Called to determine the initial header to be shown. The default + * implementation simply returns the fragment of the first header. Note + * that the returned Header object does not actually need to exist in + * your header list -- whatever its fragment is will simply be used to + * show for the initial UI. */ - public String onGetInitialFragment() { - return mHeaders.get(0).fragment; + public Header onGetInitialHeader() { + return mHeaders.get(0); } /** @@ -398,6 +435,16 @@ public abstract class PreferenceActivity extends ListActivity implements public void onBuildHeaders(List

target) { } + /** + * Call when you need to change the headers being displayed. Will result + * in onBuildHeaders() later being called to retrieve the new list. + */ + public void invalidateHeaders() { + if (!mHandler.hasMessages(MSG_BUILD_HEADERS)) { + mHandler.sendEmptyMessage(MSG_BUILD_HEADERS); + } + } + /** * Parse the given XML file as a header description, adding each * parsed Header into the target list. @@ -552,9 +599,9 @@ public abstract class PreferenceActivity extends ListActivity implements */ public void onHeaderClick(Header header, int position) { if (mSinglePane) { - startWithFragment(header.fragment); + startWithFragment(header.fragment, header.fragmentArguments); } else { - switchToHeader(header.fragment); + switchToHeader(header.fragment, header.fragmentArguments); } } @@ -565,12 +612,14 @@ public abstract class PreferenceActivity extends ListActivity implements * and fill the entire activity. * * @param fragmentName The name of the fragment to display. + * @param args Optional arguments to supply to the fragment. */ - public void startWithFragment(String fragmentName) { + public void startWithFragment(String fragmentName, Bundle args) { Intent intent = new Intent(Intent.ACTION_MAIN); intent.setClass(this, getClass()); - intent.putExtra(EXTRA_PREFS_SHOW_FRAGMENT, fragmentName); - intent.putExtra(EXTRA_PREFS_NO_HEADERS, true); + intent.putExtra(EXTRA_SHOW_FRAGMENT, fragmentName); + intent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, args); + intent.putExtra(EXTRA_NO_HEADERS, true); startActivity(intent); } @@ -579,29 +628,18 @@ public abstract class PreferenceActivity extends ListActivity implements * preference fragment. * * @param fragmentName The name of the fragment to display. + * @param args Optional arguments to supply to the fragment. */ - public void switchToHeader(String fragmentName) { + public void switchToHeader(String fragmentName, Bundle args) { popBackStack(BACK_STACK_PREFS, POP_BACK_STACK_INCLUSIVE); - Fragment f; - try { - f = Fragment.instantiate(this, fragmentName); - } catch (Exception e) { - Log.w(TAG, "Failure instantiating fragment " + fragmentName, e); - return; - } + Fragment f = Fragment.instantiate(this, fragmentName, args); openFragmentTransaction().replace(com.android.internal.R.id.prefs, f).commit(); } @Override public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) { - Fragment f; - try { - f = Fragment.instantiate(this, pref.getFragment()); - } catch (Exception e) { - Log.w(TAG, "Failure instantiating fragment " + pref.getFragment(), e); - return false; - } + Fragment f = Fragment.instantiate(this, pref.getFragment()); openFragmentTransaction().replace(com.android.internal.R.id.prefs, f) .addToBackStack(BACK_STACK_PREFS).commit(); return true; diff --git a/core/java/android/util/AndroidException.java b/core/java/android/util/AndroidException.java index a767ea1e975c2..dfe00c9bd49fb 100644 --- a/core/java/android/util/AndroidException.java +++ b/core/java/android/util/AndroidException.java @@ -27,6 +27,10 @@ public class AndroidException extends Exception { super(name); } + public AndroidException(String name, Throwable cause) { + super(name, cause); + } + public AndroidException(Exception cause) { super(cause); } diff --git a/core/java/android/util/AndroidRuntimeException.java b/core/java/android/util/AndroidRuntimeException.java index 4ed17bcd31c6c..2b824bf9cb2ae 100644 --- a/core/java/android/util/AndroidRuntimeException.java +++ b/core/java/android/util/AndroidRuntimeException.java @@ -27,6 +27,10 @@ public class AndroidRuntimeException extends RuntimeException { super(name); } + public AndroidRuntimeException(String name, Throwable cause) { + super(name, cause); + } + public AndroidRuntimeException(Exception cause) { super(cause); }