Further work on fragments:
- Implement all of the state saving and restoring machinery. This caused some flux in the API. - Add ability to have fragments that are retained across activity instances. - Fix some bugs. Change-Id: Ib6b5b0752d7f8d667cfdcd3e76d127cc9b6d901b
This commit is contained in:
135
api/current.xml
135
api/current.xml
@@ -19904,6 +19904,19 @@
|
||||
<parameter name="id" type="int">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="findFragmentByTag"
|
||||
return="android.app.Fragment"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="tag" type="java.lang.String">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="findViewById"
|
||||
return="android.view.View"
|
||||
abstract="false"
|
||||
@@ -25414,6 +25427,19 @@
|
||||
visibility="public"
|
||||
>
|
||||
</constructor>
|
||||
<method name="equals"
|
||||
return="boolean"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="o" type="java.lang.Object">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="getActivity"
|
||||
return="android.app.Activity"
|
||||
abstract="false"
|
||||
@@ -25425,6 +25451,61 @@
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="getId"
|
||||
return="int"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="getRetainInstance"
|
||||
return="boolean"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="getTag"
|
||||
return="java.lang.String"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="getView"
|
||||
return="android.view.View"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="hashCode"
|
||||
return="int"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="onAttach"
|
||||
return="void"
|
||||
abstract="false"
|
||||
@@ -25493,6 +25574,8 @@
|
||||
</parameter>
|
||||
<parameter name="container" type="android.view.ViewGroup">
|
||||
</parameter>
|
||||
<parameter name="savedInstanceState" type="android.os.Bundle">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="onDestroy"
|
||||
return="void"
|
||||
@@ -25553,7 +25636,7 @@
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="onRestoreInstanceState"
|
||||
<method name="onReady"
|
||||
return="void"
|
||||
abstract="false"
|
||||
native="false"
|
||||
@@ -25577,17 +25660,6 @@
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="onRetainNonConfigurationInstance"
|
||||
return="java.lang.Object"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="onSaveInstanceState"
|
||||
return="void"
|
||||
abstract="false"
|
||||
@@ -25623,6 +25695,19 @@
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="setRetainInstance"
|
||||
return="void"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="retain" type="boolean">
|
||||
</parameter>
|
||||
</method>
|
||||
</class>
|
||||
<interface name="FragmentTransaction"
|
||||
abstract="true"
|
||||
@@ -25643,6 +25728,8 @@
|
||||
>
|
||||
<parameter name="fragment" type="android.app.Fragment">
|
||||
</parameter>
|
||||
<parameter name="tag" type="java.lang.String">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="add"
|
||||
return="android.app.FragmentTransaction"
|
||||
@@ -181501,6 +181588,17 @@
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="isSaveFromParentEnabled"
|
||||
return="boolean"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="isScrollbarFadingEnabled"
|
||||
return="boolean"
|
||||
abstract="false"
|
||||
@@ -182979,6 +183077,19 @@
|
||||
<parameter name="enabled" type="boolean">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="setSaveFromParentEnabled"
|
||||
return="void"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="enabled" type="boolean">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="setScrollBarStyle"
|
||||
return="void"
|
||||
abstract="false"
|
||||
|
||||
@@ -42,6 +42,7 @@ import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Parcelable;
|
||||
import android.os.RemoteException;
|
||||
import android.text.Selection;
|
||||
import android.text.SpannableStringBuilder;
|
||||
@@ -77,6 +78,9 @@ import android.widget.LinearLayout;
|
||||
import com.android.internal.app.SplitActionBar;
|
||||
import com.android.internal.policy.PolicyManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* An activity is a single, focused thing that the user can do. Almost all
|
||||
* activities interact with the user, so the Activity class takes care of
|
||||
@@ -611,6 +615,7 @@ public class Activity extends ContextThemeWrapper
|
||||
private static long sInstanceCount = 0;
|
||||
|
||||
private static final String WINDOW_HIERARCHY_TAG = "android:viewHierarchyState";
|
||||
private static final String FRAGMENTS_TAG = "android:fragments";
|
||||
private static final String SAVED_DIALOG_IDS_KEY = "android:savedDialogIds";
|
||||
private static final String SAVED_DIALOGS_TAG = "android:savedDialogs";
|
||||
private static final String SAVED_DIALOG_KEY_PREFIX = "android:dialog_";
|
||||
@@ -632,8 +637,6 @@ public class Activity extends ContextThemeWrapper
|
||||
private ComponentName mComponent;
|
||||
/*package*/ ActivityInfo mActivityInfo;
|
||||
/*package*/ ActivityThread mMainThread;
|
||||
/*package*/ Object mLastNonConfigurationInstance;
|
||||
/*package*/ HashMap<String,Object> mLastNonConfigurationChildInstances;
|
||||
Activity mParent;
|
||||
boolean mCalled;
|
||||
private boolean mResumed;
|
||||
@@ -646,6 +649,13 @@ public class Activity extends ContextThemeWrapper
|
||||
/*package*/ Configuration mCurrentConfig;
|
||||
private SearchManager mSearchManager;
|
||||
|
||||
static final class NonConfigurationInstances {
|
||||
Object activity;
|
||||
HashMap<String, Object> children;
|
||||
ArrayList<Fragment> fragments;
|
||||
}
|
||||
/* package */ NonConfigurationInstances mLastNonConfigurationInstances;
|
||||
|
||||
private Window mWindow;
|
||||
|
||||
private WindowManager mWindowManager;
|
||||
@@ -660,148 +670,6 @@ public class Activity extends ContextThemeWrapper
|
||||
|
||||
final FragmentManager mFragments = new FragmentManager();
|
||||
|
||||
private final Object[] sConstructorArgs = new Object[0];
|
||||
|
||||
private static final Class[] sConstructorSignature = new Class[] { };
|
||||
|
||||
private static final HashMap<String, Constructor> sConstructorMap =
|
||||
new HashMap<String, Constructor>();
|
||||
|
||||
private final class FragmentTransactionImpl implements FragmentTransaction,
|
||||
Runnable, BackStackState {
|
||||
ArrayList<Fragment> mAdded;
|
||||
ArrayList<Fragment> mRemoved;
|
||||
int mTransition;
|
||||
int mTransitionStyle;
|
||||
boolean mAddToBackStack;
|
||||
String mName;
|
||||
boolean mCommitted;
|
||||
|
||||
public FragmentTransaction add(Fragment fragment) {
|
||||
return add(fragment, 0);
|
||||
}
|
||||
|
||||
public FragmentTransaction add(Fragment fragment, int containerViewId) {
|
||||
if (fragment.mActivity != null) {
|
||||
throw new IllegalStateException("Fragment already added: " + fragment);
|
||||
}
|
||||
if (mRemoved != null) {
|
||||
mRemoved.remove(fragment);
|
||||
}
|
||||
if (mAdded == null) {
|
||||
mAdded = new ArrayList<Fragment>();
|
||||
}
|
||||
fragment.mContainerId = containerViewId;
|
||||
mAdded.add(fragment);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FragmentTransaction replace(Fragment fragment, int containerViewId) {
|
||||
if (containerViewId == 0) {
|
||||
throw new IllegalArgumentException("Must use non-zero containerViewId");
|
||||
}
|
||||
if (mFragments.mFragments != null) {
|
||||
for (int i=0; i<mFragments.mFragments.size(); i++) {
|
||||
Fragment old = mFragments.mFragments.get(i);
|
||||
if (old.mContainerId == containerViewId) {
|
||||
remove(old);
|
||||
}
|
||||
}
|
||||
}
|
||||
return add(fragment, containerViewId);
|
||||
}
|
||||
|
||||
public FragmentTransaction remove(Fragment fragment) {
|
||||
if (fragment.mActivity == null) {
|
||||
throw new IllegalStateException("Fragment not added: " + fragment);
|
||||
}
|
||||
if (mAdded != null) {
|
||||
mAdded.remove(fragment);
|
||||
}
|
||||
if (mRemoved == null) {
|
||||
mRemoved = new ArrayList<Fragment>();
|
||||
}
|
||||
mRemoved.add(fragment);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FragmentTransaction setTransition(int transition) {
|
||||
mTransition = transition;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FragmentTransaction setTransitionStyle(int styleRes) {
|
||||
mTransitionStyle = styleRes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FragmentTransaction addToBackStack(String name) {
|
||||
mAddToBackStack = true;
|
||||
mName = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void commit() {
|
||||
if (mCommitted) throw new IllegalStateException("commit already called");
|
||||
mCommitted = true;
|
||||
mHandler.post(this);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
if (mRemoved != null) {
|
||||
for (int i=mRemoved.size()-1; i>=0; i--) {
|
||||
mFragments.removeFragment(mRemoved.get(i), mTransition,
|
||||
mTransitionStyle);
|
||||
}
|
||||
}
|
||||
if (mAdded != null) {
|
||||
for (int i=mAdded.size()-1; i>=0; i--) {
|
||||
Fragment f = mAdded.get(i);
|
||||
mFragments.addFragment(f, false);
|
||||
if (mAddToBackStack) {
|
||||
f.mBackStackNesting++;
|
||||
}
|
||||
}
|
||||
}
|
||||
mFragments.moveToState(mFragments.mCurState, mTransition,
|
||||
mTransitionStyle, true);
|
||||
if (mAddToBackStack) {
|
||||
mFragments.addBackStackState(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void popFromBackStack() {
|
||||
if (mAdded != null) {
|
||||
for (int i=mAdded.size()-1; i>=0; i--) {
|
||||
Fragment f = mAdded.get(i);
|
||||
if (mAddToBackStack) {
|
||||
f.mBackStackNesting--;
|
||||
}
|
||||
mFragments.removeFragment(f,
|
||||
FragmentManager.reverseTransit(mTransition),
|
||||
mTransitionStyle);
|
||||
}
|
||||
}
|
||||
if (mRemoved != null) {
|
||||
for (int i=mRemoved.size()-1; i>=0; i--) {
|
||||
mFragments.addFragment(mRemoved.get(i), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
public int getTransition() {
|
||||
return mTransition;
|
||||
}
|
||||
|
||||
public int getTransitionStyle() {
|
||||
return mTransitionStyle;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ManagedCursor {
|
||||
ManagedCursor(Cursor cursor) {
|
||||
mCursor = cursor;
|
||||
@@ -828,7 +696,7 @@ public class Activity extends ContextThemeWrapper
|
||||
protected static final int[] FOCUSED_STATE_SET = {com.android.internal.R.attr.state_focused};
|
||||
|
||||
private Thread mUiThread;
|
||||
private final Handler mHandler = new Handler();
|
||||
final Handler mHandler = new Handler();
|
||||
|
||||
// Used for debug only
|
||||
/*
|
||||
@@ -952,7 +820,12 @@ public class Activity extends ContextThemeWrapper
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(
|
||||
com.android.internal.R.styleable.Window_windowNoDisplay, false);
|
||||
mFragments.dispatchCreate(savedInstanceState);
|
||||
if (savedInstanceState != null) {
|
||||
Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
|
||||
mFragments.restoreAllState(p, mLastNonConfigurationInstances != null
|
||||
? mLastNonConfigurationInstances.fragments : null);
|
||||
}
|
||||
mFragments.dispatchCreate();
|
||||
mCalled = true;
|
||||
}
|
||||
|
||||
@@ -1237,6 +1110,10 @@ public class Activity extends ContextThemeWrapper
|
||||
*/
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());
|
||||
Parcelable p = mFragments.saveAllState();
|
||||
if (p != null) {
|
||||
outState.putParcelable(FRAGMENTS_TAG, p);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1541,7 +1418,8 @@ public class Activity extends ContextThemeWrapper
|
||||
* {@link #onRetainNonConfigurationInstance()}.
|
||||
*/
|
||||
public Object getLastNonConfigurationInstance() {
|
||||
return mLastNonConfigurationInstance;
|
||||
return mLastNonConfigurationInstances != null
|
||||
? mLastNonConfigurationInstances.activity : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1597,8 +1475,9 @@ public class Activity extends ContextThemeWrapper
|
||||
* @return Returns the object previously returned by
|
||||
* {@link #onRetainNonConfigurationChildInstances()}
|
||||
*/
|
||||
HashMap<String,Object> getLastNonConfigurationChildInstances() {
|
||||
return mLastNonConfigurationChildInstances;
|
||||
HashMap<String, Object> getLastNonConfigurationChildInstances() {
|
||||
return mLastNonConfigurationInstances != null
|
||||
? mLastNonConfigurationInstances.children : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1612,6 +1491,21 @@ public class Activity extends ContextThemeWrapper
|
||||
return null;
|
||||
}
|
||||
|
||||
NonConfigurationInstances retainNonConfigurationInstances() {
|
||||
Object activity = onRetainNonConfigurationInstance();
|
||||
HashMap<String, Object> children = onRetainNonConfigurationChildInstances();
|
||||
ArrayList<Fragment> fragments = mFragments.retainNonConfig();
|
||||
if (activity == null && children == null && fragments == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
NonConfigurationInstances nci = new NonConfigurationInstances();
|
||||
nci.activity = activity;
|
||||
nci.children = children;
|
||||
nci.fragments = fragments;
|
||||
return nci;
|
||||
}
|
||||
|
||||
public void onLowMemory() {
|
||||
mCalled = true;
|
||||
}
|
||||
@@ -1621,7 +1515,7 @@ public class Activity extends ContextThemeWrapper
|
||||
* this activity.
|
||||
*/
|
||||
public FragmentTransaction openFragmentTransaction() {
|
||||
return new FragmentTransactionImpl();
|
||||
return new BackStackEntry(mFragments);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1810,16 +1704,6 @@ public class Activity extends ContextThemeWrapper
|
||||
return mActionBar;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 only
|
||||
* returns fragments that are currently added to the activity's content.
|
||||
* @return The fragment if found or null otherwise.
|
||||
*/
|
||||
public Fragment findFragmentById(int id) {
|
||||
return mFragments.findFragmentById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ActionBar, locates the inflated ActionBarView,
|
||||
* initializes the ActionBar with the view, and sets mActionBar.
|
||||
@@ -1841,6 +1725,26 @@ public class Activity extends ContextThemeWrapper
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 only
|
||||
* returns fragments that are currently added to the activity's content.
|
||||
* @return The fragment if found or null otherwise.
|
||||
*/
|
||||
public Fragment findFragmentById(int id) {
|
||||
return mFragments.findFragmentById(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 only
|
||||
* returns fragments that are currently added to the activity's content.
|
||||
* @return The fragment if found or null otherwise.
|
||||
*/
|
||||
public Fragment findFragmentByTag(String tag) {
|
||||
return mFragments.findFragmentByTag(tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the activity content from a layout resource. The resource will be
|
||||
* inflated, adding all top-level views to the activity.
|
||||
@@ -2198,6 +2102,11 @@ public class Activity extends ContextThemeWrapper
|
||||
}
|
||||
|
||||
public void onContentChanged() {
|
||||
// First time content is available, let the fragment manager
|
||||
// attach all of the fragments to it.
|
||||
if (mFragments.mCurState < Fragment.CONTENT) {
|
||||
mFragments.moveToState(Fragment.CONTENT, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3960,44 +3869,42 @@ public class Activity extends ContextThemeWrapper
|
||||
TypedArray a =
|
||||
context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.Fragment);
|
||||
String fname = a.getString(com.android.internal.R.styleable.Fragment_name);
|
||||
int id = a.getInt(com.android.internal.R.styleable.Fragment_id, 0);
|
||||
int id = a.getResourceId(com.android.internal.R.styleable.Fragment_id, 0);
|
||||
String tag = a.getString(com.android.internal.R.styleable.Fragment_tag);
|
||||
a.recycle();
|
||||
|
||||
Constructor constructor = sConstructorMap.get(fname);
|
||||
Class clazz = null;
|
||||
|
||||
if (id == 0) {
|
||||
throw new IllegalArgumentException(attrs.getPositionDescription()
|
||||
+ ": Must specify unique android:id for " + fname);
|
||||
}
|
||||
|
||||
try {
|
||||
if (constructor == null) {
|
||||
// Class not found in the cache, see if it's real, and try to add it
|
||||
clazz = getClassLoader().loadClass(fname);
|
||||
constructor = clazz.getConstructor(sConstructorSignature);
|
||||
sConstructorMap.put(fname, constructor);
|
||||
// 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 (fragment == null) {
|
||||
fragment = Fragment.instantiate(this, fname);
|
||||
fragment.mFromLayout = true;
|
||||
fragment.mFragmentId = id;
|
||||
fragment.mTag = tag;
|
||||
fragment.onInflate(this, attrs);
|
||||
mFragments.addFragment(fragment, true);
|
||||
}
|
||||
Fragment fragment = (Fragment)constructor.newInstance(sConstructorArgs);
|
||||
fragment.onInflate(this, attrs);
|
||||
mFragments.addFragment(fragment, true);
|
||||
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 (NoSuchMethodException e) {
|
||||
InflateException ie = new InflateException(attrs.getPositionDescription()
|
||||
+ ": Error inflating class " + fname);
|
||||
ie.initCause(e);
|
||||
throw ie;
|
||||
|
||||
} catch (ClassNotFoundException e) {
|
||||
// If loadClass fails, we should propagate the exception.
|
||||
throw new RuntimeException(e);
|
||||
} catch (Exception e) {
|
||||
InflateException ie = new InflateException(attrs.getPositionDescription()
|
||||
+ ": Error inflating class "
|
||||
+ (clazz == null ? "<unknown>" : clazz.getName()));
|
||||
+ ": Error inflating fragment " + fname);
|
||||
ie.initCause(e);
|
||||
throw new RuntimeException(ie);
|
||||
throw ie;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4009,18 +3916,17 @@ public class Activity extends ContextThemeWrapper
|
||||
|
||||
final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token,
|
||||
Application application, Intent intent, ActivityInfo info, CharSequence title,
|
||||
Activity parent, String id, Object lastNonConfigurationInstance,
|
||||
Activity parent, String id, NonConfigurationInstances lastNonConfigurationInstances,
|
||||
Configuration config) {
|
||||
attach(context, aThread, instr, token, 0, application, intent, info, title, parent, id,
|
||||
lastNonConfigurationInstance, null, config);
|
||||
lastNonConfigurationInstances, config);
|
||||
}
|
||||
|
||||
final void attach(Context context, ActivityThread aThread,
|
||||
Instrumentation instr, IBinder token, int ident,
|
||||
Application application, Intent intent, ActivityInfo info,
|
||||
CharSequence title, Activity parent, String id,
|
||||
Object lastNonConfigurationInstance,
|
||||
HashMap<String,Object> lastNonConfigurationChildInstances,
|
||||
NonConfigurationInstances lastNonConfigurationInstances,
|
||||
Configuration config) {
|
||||
attachBaseContext(context);
|
||||
|
||||
@@ -4045,8 +3951,7 @@ public class Activity extends ContextThemeWrapper
|
||||
mTitle = title;
|
||||
mParent = parent;
|
||||
mEmbeddedID = id;
|
||||
mLastNonConfigurationInstance = lastNonConfigurationInstance;
|
||||
mLastNonConfigurationChildInstances = lastNonConfigurationChildInstances;
|
||||
mLastNonConfigurationInstances = lastNonConfigurationInstances;
|
||||
|
||||
mWindow.setWindowManager(null, mToken, mComponent.flattenToString());
|
||||
if (mParent != null) {
|
||||
@@ -4104,7 +4009,7 @@ public class Activity extends ContextThemeWrapper
|
||||
final void performResume() {
|
||||
performRestart();
|
||||
|
||||
mLastNonConfigurationInstance = null;
|
||||
mLastNonConfigurationInstances = null;
|
||||
|
||||
// First call onResume() -before- setting mResumed, so we don't
|
||||
// send out any status bar / menu notifications the client makes.
|
||||
|
||||
@@ -1300,8 +1300,7 @@ public final class ActivityThread {
|
||||
Window window;
|
||||
Activity parent;
|
||||
String embeddedID;
|
||||
Object lastNonConfigurationInstance;
|
||||
HashMap<String,Object> lastNonConfigurationChildInstances;
|
||||
Activity.NonConfigurationInstances lastNonConfigurationInstances;
|
||||
boolean paused;
|
||||
boolean stopped;
|
||||
boolean hideForNow;
|
||||
@@ -2479,7 +2478,7 @@ public final class ActivityThread {
|
||||
|
||||
public final Activity startActivityNow(Activity parent, String id,
|
||||
Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state,
|
||||
Object lastNonConfigurationInstance) {
|
||||
Activity.NonConfigurationInstances lastNonConfigurationInstances) {
|
||||
ActivityRecord r = new ActivityRecord();
|
||||
r.token = token;
|
||||
r.ident = 0;
|
||||
@@ -2488,7 +2487,7 @@ public final class ActivityThread {
|
||||
r.parent = parent;
|
||||
r.embeddedID = id;
|
||||
r.activityInfo = activityInfo;
|
||||
r.lastNonConfigurationInstance = lastNonConfigurationInstance;
|
||||
r.lastNonConfigurationInstances = lastNonConfigurationInstances;
|
||||
if (localLOGV) {
|
||||
ComponentName compname = intent.getComponent();
|
||||
String name;
|
||||
@@ -2610,14 +2609,12 @@ public final class ActivityThread {
|
||||
+ r.activityInfo.name + " with config " + config);
|
||||
activity.attach(appContext, this, getInstrumentation(), r.token,
|
||||
r.ident, app, r.intent, r.activityInfo, title, r.parent,
|
||||
r.embeddedID, r.lastNonConfigurationInstance,
|
||||
r.lastNonConfigurationChildInstances, config);
|
||||
r.embeddedID, r.lastNonConfigurationInstances, config);
|
||||
|
||||
if (customIntent != null) {
|
||||
activity.mIntent = customIntent;
|
||||
}
|
||||
r.lastNonConfigurationInstance = null;
|
||||
r.lastNonConfigurationChildInstances = null;
|
||||
r.lastNonConfigurationInstances = null;
|
||||
activity.mStartedActivity = false;
|
||||
int theme = r.activityInfo.getThemeResource();
|
||||
if (theme != 0) {
|
||||
@@ -3618,8 +3615,8 @@ public final class ActivityThread {
|
||||
}
|
||||
if (getNonConfigInstance) {
|
||||
try {
|
||||
r.lastNonConfigurationInstance
|
||||
= r.activity.onRetainNonConfigurationInstance();
|
||||
r.lastNonConfigurationInstances
|
||||
= r.activity.retainNonConfigurationInstances();
|
||||
} catch (Exception e) {
|
||||
if (!mInstrumentation.onException(r.activity, e)) {
|
||||
throw new RuntimeException(
|
||||
@@ -3628,18 +3625,6 @@ public final class ActivityThread {
|
||||
+ ": " + e.toString(), e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
r.lastNonConfigurationChildInstances
|
||||
= r.activity.onRetainNonConfigurationChildInstances();
|
||||
} catch (Exception e) {
|
||||
if (!mInstrumentation.onException(r.activity, e)) {
|
||||
throw new RuntimeException(
|
||||
"Unable to retain child activities "
|
||||
+ safeToComponentShortString(r.intent)
|
||||
+ ": " + e.toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
try {
|
||||
r.activity.mCalled = false;
|
||||
|
||||
@@ -17,46 +17,281 @@
|
||||
package android.app;
|
||||
|
||||
import android.content.ComponentCallbacks;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.SparseArray;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.Animation;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.HashMap;
|
||||
|
||||
final class FragmentState implements Parcelable {
|
||||
static final String VIEW_STATE_TAG = "android:view_state";
|
||||
|
||||
final String mClassName;
|
||||
final boolean mFromLayout;
|
||||
final int mSavedStateId;
|
||||
final int mFragmentId;
|
||||
final int mContainerId;
|
||||
final String mTag;
|
||||
final boolean mRetainInstance;
|
||||
|
||||
Bundle mSavedFragmentState;
|
||||
|
||||
Fragment mInstance;
|
||||
|
||||
public FragmentState(Fragment frag) {
|
||||
mClassName = frag.getClass().getName();
|
||||
mFromLayout = frag.mFromLayout;
|
||||
mSavedStateId = frag.mSavedStateId;
|
||||
mFragmentId = frag.mFragmentId;
|
||||
mContainerId = frag.mContainerId;
|
||||
mTag = frag.mTag;
|
||||
mRetainInstance = frag.mRetainInstance;
|
||||
}
|
||||
|
||||
public FragmentState(Parcel in) {
|
||||
mClassName = in.readString();
|
||||
mFromLayout = in.readInt() != 0;
|
||||
mSavedStateId = in.readInt();
|
||||
mFragmentId = in.readInt();
|
||||
mContainerId = in.readInt();
|
||||
mTag = in.readString();
|
||||
mRetainInstance = in.readInt() != 0;
|
||||
mSavedFragmentState = in.readBundle();
|
||||
}
|
||||
|
||||
public Fragment instantiate(Activity activity) {
|
||||
if (mFromLayout) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (mInstance != null) {
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
try {
|
||||
mInstance = Fragment.instantiate(activity, mClassName);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Unable to restore fragment " + mClassName, e);
|
||||
}
|
||||
|
||||
if (mSavedFragmentState != null) {
|
||||
mSavedFragmentState.setClassLoader(activity.getClassLoader());
|
||||
mInstance.mSavedFragmentState = mSavedFragmentState;
|
||||
mInstance.mSavedViewState
|
||||
= mSavedFragmentState.getSparseParcelableArray(VIEW_STATE_TAG);
|
||||
}
|
||||
mInstance.mSavedStateId = mSavedStateId;
|
||||
mInstance.mFragmentId = mFragmentId;
|
||||
mInstance.mContainerId = mContainerId;
|
||||
mInstance.mTag = mTag;
|
||||
mInstance.mRetainInstance = mRetainInstance;
|
||||
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(mClassName);
|
||||
dest.writeInt(mFromLayout ? 1 : 0);
|
||||
dest.writeInt(mSavedStateId);
|
||||
dest.writeInt(mFragmentId);
|
||||
dest.writeInt(mContainerId);
|
||||
dest.writeString(mTag);
|
||||
dest.writeInt(mRetainInstance ? 1 : 0);
|
||||
dest.writeBundle(mSavedFragmentState);
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<FragmentState> CREATOR
|
||||
= new Parcelable.Creator<FragmentState>() {
|
||||
public FragmentState createFromParcel(Parcel in) {
|
||||
return new FragmentState(in);
|
||||
}
|
||||
|
||||
public FragmentState[] newArray(int size) {
|
||||
return new FragmentState[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* A Fragment is a piece of an application's user interface or behavior
|
||||
* that can be placed in an {@link Activity}.
|
||||
*/
|
||||
public class Fragment implements ComponentCallbacks {
|
||||
private static final Object[] sConstructorArgs = new Object[0];
|
||||
|
||||
private static final Class[] sConstructorSignature = new Class[] { };
|
||||
|
||||
private static final HashMap<String, Constructor> sConstructorMap =
|
||||
new HashMap<String, Constructor>();
|
||||
|
||||
static final int INITIALIZING = 0; // Not yet created.
|
||||
static final int CREATED = 1; // Created.
|
||||
static final int STARTED = 2; // Created and started, not resumed.
|
||||
static final int RESUMED = 3; // Created started and resumed.
|
||||
static final int CONTENT = 2; // View hierarchy content available.
|
||||
static final int STARTED = 3; // Created and started, not resumed.
|
||||
static final int RESUMED = 4; // Created started and resumed.
|
||||
|
||||
int mState = INITIALIZING;
|
||||
|
||||
// When instantiated from saved state, this is the saved state.
|
||||
Bundle mSavedFragmentState;
|
||||
SparseArray<Parcelable> mSavedViewState;
|
||||
|
||||
// Set to true if this fragment was instantiated from a layout file.
|
||||
boolean mFromLayout;
|
||||
|
||||
// Number of active back stack entries this fragment is in.
|
||||
int mBackStackNesting;
|
||||
|
||||
// Activity this fragment is attached to.
|
||||
Activity mActivity;
|
||||
|
||||
boolean mCalled;
|
||||
// The optional identifier for this fragment -- either the container ID if it
|
||||
// was dynamically added to the view hierarchy, or the ID supplied in
|
||||
// layout.
|
||||
int mFragmentId;
|
||||
|
||||
// When a fragment is being dynamically added to the view hierarchy, this
|
||||
// is the identifier of the parent container it is being added to.
|
||||
int mContainerId;
|
||||
|
||||
// The optional named tag for this fragment -- usually used to find
|
||||
// fragments that are not part of the layout.
|
||||
String mTag;
|
||||
|
||||
// If set this fragment would like its instance retained across
|
||||
// configuration changes.
|
||||
boolean mRetainInstance;
|
||||
|
||||
// If set this fragment is being retained across the current config change.
|
||||
boolean mRetaining;
|
||||
|
||||
// Used to verify that subclasses call through to super class.
|
||||
boolean mCalled;
|
||||
|
||||
// The parent container of the fragment after dynamically added to UI.
|
||||
ViewGroup mContainer;
|
||||
|
||||
// The View generated for this fragment.
|
||||
View mView;
|
||||
|
||||
// Used for performing save state of fragments.
|
||||
int mSavedStateSeq = 0;
|
||||
int mSavedStateId;
|
||||
|
||||
public Fragment() {
|
||||
}
|
||||
|
||||
static Fragment instantiate(Activity activity, String fname)
|
||||
throws NoSuchMethodException, ClassNotFoundException,
|
||||
IllegalArgumentException, InstantiationException,
|
||||
IllegalAccessException, InvocationTargetException {
|
||||
Constructor constructor = sConstructorMap.get(fname);
|
||||
Class clazz = null;
|
||||
|
||||
if (constructor == null) {
|
||||
// Class not found in the cache, see if it's real, and try to add it
|
||||
clazz = activity.getClassLoader().loadClass(fname);
|
||||
constructor = clazz.getConstructor(sConstructorSignature);
|
||||
sConstructorMap.put(fname, constructor);
|
||||
}
|
||||
return (Fragment)constructor.newInstance(sConstructorArgs);
|
||||
}
|
||||
|
||||
void restoreViewState() {
|
||||
if (mSavedViewState != null) {
|
||||
mView.restoreHierarchyState(mSavedViewState);
|
||||
mSavedViewState = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses can not override equals().
|
||||
*/
|
||||
@Override final public boolean equals(Object o) {
|
||||
return super.equals(o);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses can not override hashCode().
|
||||
*/
|
||||
@Override final public int hashCode() {
|
||||
return super.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the identifier this fragment is known by. This is either
|
||||
* the android:id value supplied in a layout or the container view ID
|
||||
* supplied when adding the fragment.
|
||||
*/
|
||||
public int getId() {
|
||||
return mFragmentId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tag name of the fragment, if specified.
|
||||
*/
|
||||
public String getTag() {
|
||||
return mTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Activity this fragment is currently associated with.
|
||||
*/
|
||||
public Activity getActivity() {
|
||||
return mActivity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Control whether a fragment instance is retained across Activity
|
||||
* re-creation (such as from a configuration change). This can only
|
||||
* be used with fragments not in the back stack. If set, the fragment
|
||||
* lifecycle will be slightly different when an activity is recreated:
|
||||
* <ul>
|
||||
* <li> {@link #onDestroy()} will not be called (but {@link #onDetach()} still
|
||||
* will be, because the fragment is being detached from its current activity).
|
||||
* <li> {@link #onCreate(Bundle)} will not be called since the fragment
|
||||
* is not being re-created.
|
||||
* <li> {@link #onAttach(Activity)} and {@link #onReady(Bundle)} <b>will</b>
|
||||
* still be called.
|
||||
* </ul>
|
||||
*/
|
||||
public void setRetainInstance(boolean retain) {
|
||||
mRetainInstance = retain;
|
||||
}
|
||||
|
||||
public boolean getRetainInstance() {
|
||||
return mRetainInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a fragment is being created as part of a view layout
|
||||
* inflation, typically from setting the content view of an activity.
|
||||
*
|
||||
* @param activity The Activity that is inflating the fragment.
|
||||
* @param attrs The attributes at the tag where the fragment is
|
||||
* being created.
|
||||
*/
|
||||
public void onInflate(Activity activity, AttributeSet attrs) {
|
||||
mCalled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a fragment is first attached to its activity.
|
||||
* {@link #onCreate(Bundle)} will be called after this.
|
||||
*/
|
||||
public void onAttach(Activity activity) {
|
||||
mCalled = true;
|
||||
}
|
||||
@@ -65,21 +300,70 @@ public class Fragment implements ComponentCallbacks {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to do initial creation of a fragment. This is called after
|
||||
* {@link #onAttach(Activity)} and before {@link #onReady(Bundle)}.
|
||||
* @param savedInstanceState If the fragment is being re-created from
|
||||
* a previous saved state, this is the state.
|
||||
*/
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
mCalled = true;
|
||||
}
|
||||
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container) {
|
||||
/**
|
||||
* Called to have the fragment instantiate its user interface view.
|
||||
* This is optional, and non-graphical fragments can return null (which
|
||||
* is the default implementation). This will be called between
|
||||
* {@link #onCreate(Bundle)} and {@link #onReady(Bundle)}.
|
||||
*
|
||||
* @param inflater The LayoutInflater object that can be used to inflate
|
||||
* any views in the fragment,
|
||||
* @param container If non-null, this is the parent view that the fragment's
|
||||
* UI should be attached to. The fragment should not add the view itself,
|
||||
* but this can be used to generate the LayoutParams of the view.
|
||||
* @param savedInstanceState If non-null, this fragment is being re-constructed
|
||||
* from a previous saved state as given here.
|
||||
*
|
||||
* @return Return the View for the fragment's UI, or null.
|
||||
*/
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void onRestoreInstanceState(Bundle savedInstanceState) {
|
||||
public View getView() {
|
||||
return mView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the activity is ready for the fragment to run. This is
|
||||
* most useful for fragments that use {@link #setRetainInstance(boolean)}
|
||||
* instance, as this tells the fragment when it is fully associated with
|
||||
* the new activity instance. This is called after {@link #onCreate(Bundle)}
|
||||
* and before {@link #onStart()}.
|
||||
*
|
||||
* @param savedInstanceState If the fragment is being re-created from
|
||||
* a previous saved state, this is the state.
|
||||
*/
|
||||
public void onReady(Bundle savedInstanceState) {
|
||||
mCalled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the Fragment is visible to the user. This is generally
|
||||
* tied to {@link Activity#onStart() Activity.onStart} of the containing
|
||||
* Activity's lifecycle.
|
||||
*/
|
||||
public void onStart() {
|
||||
mCalled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the fragment is visible to the user and actively running.
|
||||
* This is generally
|
||||
* tied to {@link Activity#onResume() Activity.onResume} of the containing
|
||||
* Activity's lifecycle.
|
||||
*/
|
||||
public void onResume() {
|
||||
mCalled = true;
|
||||
}
|
||||
@@ -91,14 +375,20 @@ public class Fragment implements ComponentCallbacks {
|
||||
mCalled = true;
|
||||
}
|
||||
|
||||
public Object onRetainNonConfigurationInstance() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the Fragment is no longer resumed. This is generally
|
||||
* tied to {@link Activity#onPause() Activity.onPause} of the containing
|
||||
* Activity's lifecycle.
|
||||
*/
|
||||
public void onPause() {
|
||||
mCalled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the Fragment is no longer started. This is generally
|
||||
* tied to {@link Activity#onStop() Activity.onStop} of the containing
|
||||
* Activity's lifecycle.
|
||||
*/
|
||||
public void onStop() {
|
||||
mCalled = true;
|
||||
}
|
||||
@@ -107,10 +397,18 @@ public class Fragment implements ComponentCallbacks {
|
||||
mCalled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the fragment is no longer in use. This is called
|
||||
* after {@link #onStop()} and before {@link #onDetach()}.
|
||||
*/
|
||||
public void onDestroy() {
|
||||
mCalled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the fragment is no longer attached to its activity. This
|
||||
* is called after {@link #onDestroy()}.
|
||||
*/
|
||||
public void onDetach() {
|
||||
mCalled = true;
|
||||
}
|
||||
|
||||
@@ -19,17 +19,269 @@ package android.app;
|
||||
import android.content.res.TypedArray;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.SparseArray;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
interface BackStackState {
|
||||
public void popFromBackStack();
|
||||
public String getName();
|
||||
public int getTransition();
|
||||
public int getTransitionStyle();
|
||||
final class BackStackEntry implements FragmentTransaction, Runnable {
|
||||
final FragmentManager mManager;
|
||||
|
||||
ArrayList<Fragment> mAdded;
|
||||
ArrayList<Fragment> mRemoved;
|
||||
int mTransition;
|
||||
int mTransitionStyle;
|
||||
boolean mAddToBackStack;
|
||||
String mName;
|
||||
boolean mCommitted;
|
||||
|
||||
public BackStackEntry(FragmentManager manager) {
|
||||
mManager = manager;
|
||||
}
|
||||
|
||||
public FragmentTransaction add(Fragment fragment, String tag) {
|
||||
fragment.mTag = tag;
|
||||
return add(fragment, 0);
|
||||
}
|
||||
|
||||
public FragmentTransaction add(Fragment fragment, int containerViewId) {
|
||||
if (fragment.mActivity != null) {
|
||||
throw new IllegalStateException("Fragment already added: " + fragment);
|
||||
}
|
||||
if (mRemoved != null) {
|
||||
mRemoved.remove(fragment);
|
||||
}
|
||||
if (mAdded == null) {
|
||||
mAdded = new ArrayList<Fragment>();
|
||||
}
|
||||
fragment.mContainerId = fragment.mFragmentId = containerViewId;
|
||||
mAdded.add(fragment);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FragmentTransaction replace(Fragment fragment, int containerViewId) {
|
||||
if (containerViewId == 0) {
|
||||
throw new IllegalArgumentException("Must use non-zero containerViewId");
|
||||
}
|
||||
if (mManager.mFragments != null) {
|
||||
for (int i=0; i<mManager.mFragments.size(); i++) {
|
||||
Fragment old = mManager.mFragments.get(i);
|
||||
if (old.mContainerId == containerViewId) {
|
||||
remove(old);
|
||||
}
|
||||
}
|
||||
}
|
||||
return add(fragment, containerViewId);
|
||||
}
|
||||
|
||||
public FragmentTransaction remove(Fragment fragment) {
|
||||
if (fragment.mActivity == null) {
|
||||
throw new IllegalStateException("Fragment not added: " + fragment);
|
||||
}
|
||||
if (mAdded != null) {
|
||||
mAdded.remove(fragment);
|
||||
}
|
||||
if (mRemoved == null) {
|
||||
mRemoved = new ArrayList<Fragment>();
|
||||
}
|
||||
mRemoved.add(fragment);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FragmentTransaction setTransition(int transition) {
|
||||
mTransition = transition;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FragmentTransaction setTransitionStyle(int styleRes) {
|
||||
mTransitionStyle = styleRes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FragmentTransaction addToBackStack(String name) {
|
||||
mAddToBackStack = true;
|
||||
mName = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void commit() {
|
||||
if (mCommitted) throw new IllegalStateException("commit already called");
|
||||
mCommitted = true;
|
||||
mManager.mActivity.mHandler.post(this);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
if (mRemoved != null) {
|
||||
for (int i=mRemoved.size()-1; i>=0; i--) {
|
||||
mManager.removeFragment(mRemoved.get(i), mTransition,
|
||||
mTransitionStyle);
|
||||
}
|
||||
}
|
||||
if (mAdded != null) {
|
||||
for (int i=mAdded.size()-1; i>=0; i--) {
|
||||
Fragment f = mAdded.get(i);
|
||||
mManager.addFragment(f, false);
|
||||
if (mAddToBackStack) {
|
||||
f.mBackStackNesting++;
|
||||
}
|
||||
}
|
||||
}
|
||||
mManager.moveToState(mManager.mCurState, mTransition,
|
||||
mTransitionStyle, true);
|
||||
if (mAddToBackStack) {
|
||||
mManager.addBackStackState(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void popFromBackStack() {
|
||||
if (mAdded != null) {
|
||||
for (int i=mAdded.size()-1; i>=0; i--) {
|
||||
Fragment f = mAdded.get(i);
|
||||
if (mAddToBackStack) {
|
||||
f.mBackStackNesting--;
|
||||
}
|
||||
mManager.removeFragment(f,
|
||||
FragmentManager.reverseTransit(mTransition),
|
||||
mTransitionStyle);
|
||||
}
|
||||
}
|
||||
if (mRemoved != null) {
|
||||
for (int i=mRemoved.size()-1; i>=0; i--) {
|
||||
mManager.addFragment(mRemoved.get(i), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
public int getTransition() {
|
||||
return mTransition;
|
||||
}
|
||||
|
||||
public int getTransitionStyle() {
|
||||
return mTransitionStyle;
|
||||
}
|
||||
}
|
||||
|
||||
final class BackStackState implements Parcelable {
|
||||
final int[] mAdded;
|
||||
final int[] mRemoved;
|
||||
final int mTransition;
|
||||
final int mTransitionStyle;
|
||||
final String mName;
|
||||
|
||||
public BackStackState(FragmentManager fm, BackStackEntry bse) {
|
||||
mAdded = buildFragmentStateList(fm, bse.mAdded);
|
||||
mRemoved = buildFragmentStateList(fm, bse.mRemoved);
|
||||
mTransition = bse.mTransition;
|
||||
mTransitionStyle = bse.mTransitionStyle;
|
||||
mName = bse.mName;
|
||||
}
|
||||
|
||||
public BackStackState(Parcel in) {
|
||||
mAdded = in.createIntArray();
|
||||
mRemoved = in.createIntArray();
|
||||
mTransition = in.readInt();
|
||||
mTransitionStyle = in.readInt();
|
||||
mName = in.readString();
|
||||
}
|
||||
|
||||
public BackStackEntry instantiate(FragmentManager fm) {
|
||||
BackStackEntry bse = new BackStackEntry(fm);
|
||||
bse.mAdded = buildFragmentList(fm, mAdded);
|
||||
bse.mRemoved = buildFragmentList(fm, mRemoved);
|
||||
bse.mTransition = mTransition;
|
||||
bse.mTransitionStyle = mTransitionStyle;
|
||||
bse.mName = mName;
|
||||
return bse;
|
||||
}
|
||||
|
||||
static int[] buildFragmentStateList(FragmentManager fm, ArrayList<Fragment> frags) {
|
||||
if (frags == null) return null;
|
||||
final int N = frags.size();
|
||||
int[] ids = new int[N];
|
||||
for (int i=0; i<N; i++) {
|
||||
FragmentState fs = fm.saveFragment(frags.get(i));
|
||||
ids[i] = fs.mSavedStateId;
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
static ArrayList<Fragment> buildFragmentList(FragmentManager fm, int[] states) {
|
||||
if (states == null) return null;
|
||||
final int N = states.length;
|
||||
ArrayList<Fragment> frags = new ArrayList<Fragment>(N);
|
||||
for (int i=0; i<N; i++) {
|
||||
frags.add(fm.mRestoredFragments.get(states[i]).instantiate(fm.mActivity));
|
||||
}
|
||||
return frags;
|
||||
}
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeIntArray(mAdded);
|
||||
dest.writeIntArray(mRemoved);
|
||||
dest.writeInt(mTransition);
|
||||
dest.writeInt(mTransitionStyle);
|
||||
dest.writeString(mName);
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<BackStackState> CREATOR
|
||||
= new Parcelable.Creator<BackStackState>() {
|
||||
public BackStackState createFromParcel(Parcel in) {
|
||||
return new BackStackState(in);
|
||||
}
|
||||
|
||||
public BackStackState[] newArray(int size) {
|
||||
return new BackStackState[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
final class FragmentManagerState implements Parcelable {
|
||||
FragmentState[] mFragments;
|
||||
int[] mAdded;
|
||||
BackStackState[] mBackStack;
|
||||
|
||||
public FragmentManagerState() {
|
||||
}
|
||||
|
||||
public FragmentManagerState(Parcel in) {
|
||||
mFragments = in.createTypedArray(FragmentState.CREATOR);
|
||||
mAdded = in.createIntArray();
|
||||
mBackStack = in.createTypedArray(BackStackState.CREATOR);
|
||||
}
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeTypedArray(mFragments, flags);
|
||||
dest.writeIntArray(mAdded);
|
||||
dest.writeTypedArray(mBackStack, flags);
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<FragmentManagerState> CREATOR
|
||||
= new Parcelable.Creator<FragmentManagerState>() {
|
||||
public FragmentManagerState createFromParcel(Parcel in) {
|
||||
return new FragmentManagerState(in);
|
||||
}
|
||||
|
||||
public FragmentManagerState[] newArray(int size) {
|
||||
return new FragmentManagerState[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -38,11 +290,20 @@ interface BackStackState {
|
||||
*/
|
||||
public class FragmentManager {
|
||||
ArrayList<Fragment> mFragments;
|
||||
ArrayList<BackStackState> mBackStack;
|
||||
ArrayList<BackStackEntry> mBackStack;
|
||||
|
||||
int mCurState = Fragment.INITIALIZING;
|
||||
Activity mActivity;
|
||||
|
||||
int mSaveStateSeq = 0;
|
||||
|
||||
// Temporary vars for state save and restore.
|
||||
int mCurSaveId = 0;
|
||||
HashMap<Fragment, FragmentState> mSavedFragments;
|
||||
SparseArray<FragmentState> mRestoredFragments;
|
||||
Bundle mStateBundle = null;
|
||||
SparseArray<Parcelable> mStateArray = null;
|
||||
|
||||
Animation loadAnimation(Fragment fragment, int transit, boolean enter,
|
||||
int transitionStyle) {
|
||||
Animation animObj = fragment.onCreateAnimation(transitionStyle, enter);
|
||||
@@ -89,32 +350,60 @@ public class FragmentManager {
|
||||
throw new SuperNotCalledException("Fragment " + f
|
||||
+ " did not call through to super.onAttach()");
|
||||
}
|
||||
f.mCalled = false;
|
||||
f.onCreate(null);
|
||||
if (!f.mCalled) {
|
||||
throw new SuperNotCalledException("Fragment " + f
|
||||
+ " did not call through to super.onCreate()");
|
||||
}
|
||||
|
||||
ViewGroup container = null;
|
||||
if (f.mContainerId != 0) {
|
||||
container = (ViewGroup)mActivity.findViewById(f.mContainerId);
|
||||
if (container == null) {
|
||||
throw new IllegalArgumentException("New view found for id 0x"
|
||||
+ Integer.toHexString(f.mContainerId)
|
||||
+ " for fragment " + f);
|
||||
if (!f.mRetaining) {
|
||||
f.mCalled = false;
|
||||
f.onCreate(f.mSavedFragmentState);
|
||||
if (!f.mCalled) {
|
||||
throw new SuperNotCalledException("Fragment " + f
|
||||
+ " did not call through to super.onCreate()");
|
||||
}
|
||||
}
|
||||
f.mContainer = container;
|
||||
f.mView = f.onCreateView(mActivity.getLayoutInflater(), container);
|
||||
if (container != null && f.mView != null) {
|
||||
Animation anim = loadAnimation(f, transit, true, transitionStyle);
|
||||
if (anim != null) {
|
||||
f.mView.setAnimation(anim);
|
||||
}
|
||||
container.addView(f.mView);
|
||||
f.mRetaining = false;
|
||||
if (f.mFromLayout) {
|
||||
// For fragments that are part of the content view
|
||||
// layout, we need to instantiate the view immediately
|
||||
// and the inflater will take care of adding it.
|
||||
f.mView = f.onCreateView(mActivity.getLayoutInflater(),
|
||||
null, f.mSavedFragmentState);
|
||||
}
|
||||
case Fragment.CONTENT:
|
||||
if (newState > Fragment.CONTENT) {
|
||||
if (!f.mFromLayout) {
|
||||
ViewGroup container = null;
|
||||
if (f.mContainerId != 0) {
|
||||
container = (ViewGroup)mActivity.findViewById(f.mContainerId);
|
||||
if (container == null) {
|
||||
throw new IllegalArgumentException("New view found for id 0x"
|
||||
+ Integer.toHexString(f.mContainerId)
|
||||
+ " for fragment " + f);
|
||||
}
|
||||
}
|
||||
f.mContainer = container;
|
||||
f.mView = f.onCreateView(mActivity.getLayoutInflater(),
|
||||
container, f.mSavedFragmentState);
|
||||
if (f.mView != null) {
|
||||
f.mView.setSaveFromParentEnabled(false);
|
||||
if (container != null) {
|
||||
Animation anim = loadAnimation(f, transit, true,
|
||||
transitionStyle);
|
||||
if (anim != null) {
|
||||
f.mView.setAnimation(anim);
|
||||
}
|
||||
container.addView(f.mView);
|
||||
f.restoreViewState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
f.mCalled = false;
|
||||
f.onReady(f.mSavedFragmentState);
|
||||
if (!f.mCalled) {
|
||||
throw new SuperNotCalledException("Fragment " + f
|
||||
+ " did not call through to super.onReady()");
|
||||
}
|
||||
f.mSavedFragmentState = null;
|
||||
}
|
||||
|
||||
case Fragment.CREATED:
|
||||
if (newState > Fragment.CREATED) {
|
||||
f.mCalled = false;
|
||||
@@ -154,24 +443,39 @@ public class FragmentManager {
|
||||
+ " did not call through to super.onStop()");
|
||||
}
|
||||
}
|
||||
case Fragment.CREATED:
|
||||
if (newState < Fragment.CREATED) {
|
||||
if (f.mContainer != null) {
|
||||
Animation anim = loadAnimation(f, transit, false, transitionStyle);
|
||||
if (anim != null) {
|
||||
f.mView.setAnimation(anim);
|
||||
case Fragment.CONTENT:
|
||||
if (newState < Fragment.CONTENT) {
|
||||
if (f.mView != null) {
|
||||
// Need to save the current view state if not
|
||||
// done already.
|
||||
if (!mActivity.isFinishing()) {
|
||||
saveFragmentViewState(f);
|
||||
}
|
||||
if (f.mContainer != null) {
|
||||
if (mCurState > Fragment.INITIALIZING) {
|
||||
Animation anim = loadAnimation(f, transit, false,
|
||||
transitionStyle);
|
||||
if (anim != null) {
|
||||
f.mView.setAnimation(anim);
|
||||
}
|
||||
}
|
||||
f.mContainer.removeView(f.mView);
|
||||
}
|
||||
f.mContainer.removeView(f.mView);
|
||||
}
|
||||
f.mContainer = null;
|
||||
f.mView = null;
|
||||
|
||||
f.mCalled = false;
|
||||
f.onDestroy();
|
||||
if (!f.mCalled) {
|
||||
throw new SuperNotCalledException("Fragment " + f
|
||||
+ " did not call through to super.onDestroy()");
|
||||
}
|
||||
case Fragment.CREATED:
|
||||
if (newState < Fragment.CREATED) {
|
||||
if (!f.mRetaining) {
|
||||
f.mCalled = false;
|
||||
f.onDestroy();
|
||||
if (!f.mCalled) {
|
||||
throw new SuperNotCalledException("Fragment " + f
|
||||
+ " did not call through to super.onDestroy()");
|
||||
}
|
||||
}
|
||||
|
||||
f.mCalled = false;
|
||||
f.onDetach();
|
||||
if (!f.mCalled) {
|
||||
@@ -227,7 +531,7 @@ public class FragmentManager {
|
||||
if (mFragments != null) {
|
||||
for (int i=mFragments.size()-1; i>=0; i--) {
|
||||
Fragment f = mFragments.get(i);
|
||||
if (f.mContainerId == id) {
|
||||
if (f.mFragmentId == id) {
|
||||
return f;
|
||||
}
|
||||
}
|
||||
@@ -235,9 +539,21 @@ public class FragmentManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void addBackStackState(BackStackState state) {
|
||||
public Fragment findFragmentByTag(String tag) {
|
||||
if (mFragments != null && tag != null) {
|
||||
for (int i=mFragments.size()-1; i>=0; i--) {
|
||||
Fragment f = mFragments.get(i);
|
||||
if (tag.equals(f.mTag)) {
|
||||
return f;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void addBackStackState(BackStackEntry state) {
|
||||
if (mBackStack == null) {
|
||||
mBackStack = new ArrayList<BackStackState>();
|
||||
mBackStack = new ArrayList<BackStackEntry>();
|
||||
}
|
||||
mBackStack.add(state);
|
||||
}
|
||||
@@ -251,7 +567,7 @@ public class FragmentManager {
|
||||
if (last < 0) {
|
||||
return false;
|
||||
}
|
||||
final BackStackState bss = mBackStack.remove(last);
|
||||
final BackStackEntry bss = mBackStack.remove(last);
|
||||
handler.post(new Runnable() {
|
||||
public void run() {
|
||||
bss.popFromBackStack();
|
||||
@@ -262,7 +578,7 @@ public class FragmentManager {
|
||||
} else {
|
||||
int index = mBackStack.size()-1;
|
||||
while (index >= 0) {
|
||||
BackStackState bss = mBackStack.get(index);
|
||||
BackStackEntry bss = mBackStack.get(index);
|
||||
if (name.equals(bss.getName())) {
|
||||
break;
|
||||
}
|
||||
@@ -270,7 +586,8 @@ public class FragmentManager {
|
||||
if (index < 0 || index == mBackStack.size()-1) {
|
||||
return false;
|
||||
}
|
||||
final ArrayList<BackStackState> states = new ArrayList<BackStackState>();
|
||||
final ArrayList<BackStackEntry> states
|
||||
= new ArrayList<BackStackEntry>();
|
||||
for (int i=mBackStack.size()-1; i>index; i--) {
|
||||
states.add(mBackStack.remove(i));
|
||||
}
|
||||
@@ -286,12 +603,189 @@ public class FragmentManager {
|
||||
return true;
|
||||
}
|
||||
|
||||
ArrayList<Fragment> retainNonConfig() {
|
||||
ArrayList<Fragment> fragments = null;
|
||||
if (mFragments != null) {
|
||||
for (int i=0; i<mFragments.size(); i++) {
|
||||
Fragment f = mFragments.get(i);
|
||||
if (f.mBackStackNesting <= 0 && f.mRetainInstance && f.mTag != null) {
|
||||
if (fragments == null) {
|
||||
fragments = new ArrayList<Fragment>();
|
||||
}
|
||||
fragments.add(f);
|
||||
f.mRetaining = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return fragments;
|
||||
}
|
||||
|
||||
void saveFragmentViewState(Fragment f) {
|
||||
if (f.mSavedViewState != null) {
|
||||
return;
|
||||
}
|
||||
if (mStateArray == null) {
|
||||
mStateArray = new SparseArray<Parcelable>();
|
||||
}
|
||||
f.mView.saveHierarchyState(mStateArray);
|
||||
if (mStateArray.size() > 0) {
|
||||
f.mSavedViewState = mStateArray;
|
||||
mStateArray = null;
|
||||
}
|
||||
}
|
||||
|
||||
FragmentState saveFragment(Fragment f) {
|
||||
if (mSavedFragments != null) {
|
||||
FragmentState fs = mSavedFragments.get(f);
|
||||
if (fs != null) {
|
||||
return fs;
|
||||
}
|
||||
} else {
|
||||
mSavedFragments = new HashMap<Fragment, FragmentState>();
|
||||
}
|
||||
|
||||
f.mSavedStateSeq = mSaveStateSeq;
|
||||
f.mSavedStateId = ++mCurSaveId;
|
||||
|
||||
FragmentState fs = new FragmentState(f);
|
||||
mSavedFragments.put(f, fs);
|
||||
|
||||
if (mStateBundle == null) {
|
||||
mStateBundle = new Bundle();
|
||||
}
|
||||
f.onSaveInstanceState(mStateBundle);
|
||||
if (!mStateBundle.isEmpty()) {
|
||||
fs.mSavedFragmentState = mStateBundle;
|
||||
mStateBundle = null;
|
||||
}
|
||||
|
||||
if (f.mView != null) {
|
||||
saveFragmentViewState(f);
|
||||
if (f.mSavedViewState != null) {
|
||||
if (fs.mSavedFragmentState == null) {
|
||||
fs.mSavedFragmentState = new Bundle();
|
||||
}
|
||||
fs.mSavedFragmentState.putSparseParcelableArray(
|
||||
FragmentState.VIEW_STATE_TAG, f.mSavedViewState);
|
||||
}
|
||||
}
|
||||
|
||||
return fs;
|
||||
}
|
||||
|
||||
Parcelable saveAllState() {
|
||||
mSavedFragments = null;
|
||||
mSaveStateSeq++;
|
||||
|
||||
if (mFragments == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int[] added = null;
|
||||
BackStackState[] backStack = null;
|
||||
|
||||
// First collect all active fragments.
|
||||
int N = mFragments.size();
|
||||
if (N > 0) {
|
||||
added = new int[N];
|
||||
for (int i=0; i<N; i++) {
|
||||
added[i] = saveFragment(mFragments.get(i)).mSavedStateId;
|
||||
}
|
||||
}
|
||||
|
||||
// Now save back stack.
|
||||
if (mBackStack != null) {
|
||||
N = mBackStack.size();
|
||||
if (N > 0) {
|
||||
backStack = new BackStackState[N];
|
||||
for (int i=0; i<N; i++) {
|
||||
backStack[i] = new BackStackState(this, mBackStack.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mSavedFragments == null) {
|
||||
return null;
|
||||
}
|
||||
N = mSavedFragments.size();
|
||||
if (N <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
FragmentManagerState fms = new FragmentManagerState();
|
||||
fms.mFragments = new FragmentState[N];
|
||||
int i = 0;
|
||||
for (FragmentState fs : mSavedFragments.values()) {
|
||||
fms.mFragments[i] = fs;
|
||||
i++;
|
||||
}
|
||||
fms.mAdded = added;
|
||||
fms.mBackStack = backStack;
|
||||
return fms;
|
||||
}
|
||||
|
||||
void restoreAllState(Parcelable state, ArrayList<Fragment> nonConfig) {
|
||||
// If there is no saved state at all, then there can not be
|
||||
// any nonConfig fragments either, so that is that.
|
||||
if (state == null) return;
|
||||
FragmentManagerState fms = (FragmentManagerState)state;
|
||||
if (fms.mFragments == null) return;
|
||||
|
||||
// First build our lookup table of all known Fragment objects.
|
||||
mRestoredFragments = new SparseArray<FragmentState>();
|
||||
for (int i=0; i<fms.mFragments.length; i++) {
|
||||
FragmentState fs = fms.mFragments[i];
|
||||
mRestoredFragments.put(fs.mSavedStateId, fs);
|
||||
}
|
||||
|
||||
// Stick any non-config instances we are retaining directly
|
||||
// into the lookup table, so we don't try to instantiate them again.
|
||||
if (nonConfig != null) {
|
||||
for (int i=0; i<nonConfig.size(); i++) {
|
||||
Fragment f = nonConfig.get(i);
|
||||
FragmentState fs = mRestoredFragments.get(f.mSavedStateId);
|
||||
fs.mInstance = f;
|
||||
f.mSavedViewState = null;
|
||||
if (fs.mSavedFragmentState != null) {
|
||||
f.mSavedViewState = fs.mSavedFragmentState.getSparseParcelableArray(
|
||||
FragmentState.VIEW_STATE_TAG);
|
||||
}
|
||||
addFragment(f, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Now build our data structures from the saved state, instantiating
|
||||
// the fragment objects as needed.
|
||||
if (fms.mAdded != null) {
|
||||
if (mFragments == null) {
|
||||
mFragments = new ArrayList<Fragment>(fms.mAdded.length);
|
||||
}
|
||||
for (int i=0; i<fms.mAdded.length; i++) {
|
||||
FragmentState fs = mRestoredFragments.get(fms.mAdded[i]);
|
||||
Fragment f = fs.instantiate(mActivity);
|
||||
// This will return null if this is a layout fragment,
|
||||
// since the instance for such a fragment will be created
|
||||
// later during layout inflation.
|
||||
if (f != null) {
|
||||
mFragments.add(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fms.mBackStack != null) {
|
||||
mBackStack = new ArrayList<BackStackEntry>(fms.mBackStack.length);
|
||||
for (int i=0; i<fms.mBackStack.length; i++) {
|
||||
BackStackEntry bse = fms.mBackStack[i].instantiate(this);
|
||||
mBackStack.add(bse);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void attachActivity(Activity activity) {
|
||||
if (mActivity != null) throw new IllegalStateException();
|
||||
mActivity = activity;
|
||||
}
|
||||
|
||||
public void dispatchCreate(Bundle state) {
|
||||
public void dispatchCreate() {
|
||||
moveToState(Fragment.CREATED, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ package android.app;
|
||||
* API for performing a set of Fragment operations.
|
||||
*/
|
||||
public interface FragmentTransaction {
|
||||
public FragmentTransaction add(Fragment fragment);
|
||||
public FragmentTransaction add(Fragment fragment, String tag);
|
||||
public FragmentTransaction add(Fragment fragment, int containerViewId);
|
||||
public FragmentTransaction replace(Fragment fragment, int containerViewId);
|
||||
public FragmentTransaction remove(Fragment fragment);
|
||||
|
||||
@@ -997,8 +997,10 @@ public class Instrumentation {
|
||||
IllegalAccessException {
|
||||
Activity activity = (Activity)clazz.newInstance();
|
||||
ActivityThread aThread = null;
|
||||
activity.attach(context, aThread, this, token, application, intent, info, title,
|
||||
parent, id, lastNonConfigurationInstance, new Configuration());
|
||||
activity.attach(context, aThread, this, token, application, intent,
|
||||
info, title, parent, id,
|
||||
(Activity.NonConfigurationInstances)lastNonConfigurationInstance,
|
||||
new Configuration());
|
||||
return activity;
|
||||
}
|
||||
|
||||
|
||||
@@ -112,11 +112,16 @@ public class LocalActivityManager {
|
||||
|
||||
if (r.curState == INITIALIZING) {
|
||||
// Get the lastNonConfigurationInstance for the activity
|
||||
HashMap<String,Object> lastNonConfigurationInstances =
|
||||
mParent.getLastNonConfigurationChildInstances();
|
||||
Object instance = null;
|
||||
HashMap<String, Object> lastNonConfigurationInstances =
|
||||
mParent.getLastNonConfigurationChildInstances();
|
||||
Object instanceObj = null;
|
||||
if (lastNonConfigurationInstances != null) {
|
||||
instance = lastNonConfigurationInstances.get(r.id);
|
||||
instanceObj = lastNonConfigurationInstances.get(r.id);
|
||||
}
|
||||
Activity.NonConfigurationInstances instance = null;
|
||||
if (instanceObj != null) {
|
||||
instance = new Activity.NonConfigurationInstances();
|
||||
instance.activity = instanceObj;
|
||||
}
|
||||
|
||||
// We need to have always created the activity.
|
||||
|
||||
@@ -886,6 +886,20 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
|
||||
*/
|
||||
public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
|
||||
|
||||
/**
|
||||
* <p>Indicates that the view hierarchy should stop saving state when
|
||||
* it reaches this view. If state saving is initiated immediately at
|
||||
* the view, it will be allowed.
|
||||
* {@hide}
|
||||
*/
|
||||
static final int PARENT_SAVE_DISABLED = 0x20000000;
|
||||
|
||||
/**
|
||||
* <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
|
||||
* {@hide}
|
||||
*/
|
||||
static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
|
||||
|
||||
/**
|
||||
* View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
|
||||
* should add all focusable Views regardless if they are focusable in touch mode.
|
||||
@@ -3341,6 +3355,38 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Indicates whether the entire hierarchy under this view will save its
|
||||
* state when a state saving traversal occurs from its parent. The default
|
||||
* is true; if false, these views will not be saved unless
|
||||
* {@link #saveHierarchyState(SparseArray)} is called directly on this view.
|
||||
*
|
||||
* @return Returns true if the view state saving from parent is enabled, else false.
|
||||
*
|
||||
* @see #setSaveFromParentEnabled(boolean)
|
||||
*/
|
||||
public boolean isSaveFromParentEnabled() {
|
||||
return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls whether the entire hierarchy under this view will save its
|
||||
* state when a state saving traversal occurs from its parent. The default
|
||||
* is true; if false, these views will not be saved unless
|
||||
* {@link #saveHierarchyState(SparseArray)} is called directly on this view.
|
||||
*
|
||||
* @param enabled Set to false to <em>disable</em> state saving, or true
|
||||
* (the default) to allow it.
|
||||
*
|
||||
* @see #isSaveFromParentEnabled()
|
||||
* @see #setId(int)
|
||||
* @see #onSaveInstanceState()
|
||||
*/
|
||||
public void setSaveFromParentEnabled(boolean enabled) {
|
||||
setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether this View is able to take focus.
|
||||
*
|
||||
|
||||
@@ -1181,7 +1181,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|
||||
final int count = mChildrenCount;
|
||||
final View[] children = mChildren;
|
||||
for (int i = 0; i < count; i++) {
|
||||
children[i].dispatchSaveInstanceState(container);
|
||||
View c = children[i];
|
||||
if ((c.mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED) {
|
||||
c.dispatchSaveInstanceState(container);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1206,7 +1209,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|
||||
final int count = mChildrenCount;
|
||||
final View[] children = mChildren;
|
||||
for (int i = 0; i < count; i++) {
|
||||
children[i].dispatchRestoreInstanceState(container);
|
||||
View c = children[i];
|
||||
if ((c.mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED) {
|
||||
c.dispatchRestoreInstanceState(container);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user