Fragment FragmentManager FragmentTransaction 详解
例如, 一个新闻应用可以在屏幕左侧使用一个fragment来展示一个文章的列表, 然后在屏幕右侧使用另一个fragment来展示一篇文章 – 2个fragment并排显示在相同的一个activity中, 并且每一个fragment拥有它自己的一套生命周期回调方法,并且处理它们自己的用户输入事件. 因此, 取代使用一个activity来选择一篇文章,而另一个activity来阅读文章 的方式, 用户可以在相同的activity中选择一篇文章并且阅读, 如图所示:
Fragment 与Activity的关系
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
- <fragment
- android:id="@+id/id_fragment_title"
- android:name="com.android.example.TitleFragment"
- android:layout_width="fill_parent"
- android:layout_height="45dp" />
- <fragment
- android:layout_below="@id/id_fragment_title"
- android:id="@+id/id_fragment_content"
- android:name="com.android.example.ContentFragment"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent" />
- </RelativeLayout>
很明显,我们的Activity将会由上下两个fragment组成,也就是简单的将我们的屏幕划分成2块区域,2块区域可以独立处理自己的逻辑。Fragment总是存在于Activity中。
- protected void onCreate(Bundle savedInstanceState) {
- ........
- mFragments.dispatchCreate();
- ........
- }
其他的,我们先不关心,在Activity的Created之后(中),唯一能和fragment关联上的只有mFragments,通过源码我们知道
- final FragmentManagerImpl mFragments = new FragmentManagerImpl();
- public void dispatchCreate() {
- mStateSaved = false;
- moveToState(Fragment.CREATED, false);
- }
似乎什么都没有做,其实不然,每一个Activity都有一个FragmentManager,作为Fragment的管理类,FragmentManager自然管理者Activity对应所有的fragment,那么我们的核心自然就在moveToState
- void moveToState(int newState, int transit, int transitStyle, boolean always) {
- if (mActivity == null && newState != Fragment.INITIALIZING) {
- throw new IllegalStateException("No activity");
- }
- if (!always && mCurState == newState) {
- return;
- }
- mCurState = newState;
- if (mActive != null) {
- boolean loadersRunning = false;
- for (int i=0; i<mActive.size(); i++) {
- Fragment f = mActive.get(i);
- if (f != null) {
- moveToState(f, newState, transit, transitStyle, false);
- if (f.mLoaderManager != null) {
- loadersRunning |= f.mLoaderManager.hasRunningLoaders();
- }
- }
- }
- if (!loadersRunning) {
- startPendingDeferredFragments();
- }
- if (mNeedMenuInvalidate && mActivity != null && mCurState == Fragment.RESUMED) {
- mActivity.invalidateOptionsMenu();
- mNeedMenuInvalidate = false;
- }
- }
- }
- void moveToState(Fragment f, int newState, int transit, int transitionStyle,
- boolean keepActive) {
- if (DEBUG && false) Log.v(TAG, "moveToState: " + f
- + " oldState=" + f.mState + " newState=" + newState
- + " mRemoving=" + f.mRemoving + " Callers=" + Debug.getCallers(5));
- // Fragments that are not currently added will sit in the onCreate() state.
- if ((!f.mAdded || f.mDetached) && newState > Fragment.CREATED) {
- newState = Fragment.CREATED;
- }
- if (f.mRemoving && newState > f.mState) {
- // While removing a fragment, we can't change it to a higher state.
- newState = f.mState;
- }
- // Defer start if requested; don't allow it to move to STARTED or higher
- // if it's not already started.
- if (f.mDeferStart && f.mState < Fragment.STARTED && newState > Fragment.STOPPED) {
- newState = Fragment.STOPPED;
- }
- if (f.mState < newState) {
- // For fragments that are created from a layout, when restoring from
- // state we don't want to allow them to be created until they are
- // being reloaded from the layout.
- if (f.mFromLayout && !f.mInLayout) {
- return;
- }
- if (f.mAnimatingAway != null) {
- // The fragment is currently being animated... but! Now we
- // want to move our state back up. Give up on waiting for the
- // animation, move to whatever the final state should be once
- // the animation is done, and then we can proceed from there.
- f.mAnimatingAway = null;
- moveToState(f, f.mStateAfterAnimating, 0, 0, true);
- }
- switch (f.mState) {
- case Fragment.INITIALIZING:
- if (DEBUG) Log.v(TAG, "moveto CREATED: " + f);
- if (f.mSavedFragmentState != null) {
- f.mSavedViewState = f.mSavedFragmentState.getSparseParcelableArray(
- FragmentManagerImpl.VIEW_STATE_TAG);
- f.mTarget = getFragment(f.mSavedFragmentState,
- FragmentManagerImpl.TARGET_STATE_TAG);
- if (f.mTarget != null) {
- f.mTargetRequestCode = f.mSavedFragmentState.getInt(
- FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG, 0);
- }
- f.mUserVisibleHint = f.mSavedFragmentState.getBoolean(
- FragmentManagerImpl.USER_VISIBLE_HINT_TAG, true);
- if (!f.mUserVisibleHint) {
- f.mDeferStart = true;
- if (newState > Fragment.STOPPED) {
- newState = Fragment.STOPPED;
- }
- }
- }
- f.mActivity = mActivity;
- f.mParentFragment = mParent;
- f.mFragmentManager = mParent != null
- ? mParent.mChildFragmentManager : mActivity.mFragments;
- f.mCalled = false;
- f.onAttach(mActivity);
- if (!f.mCalled) {
- throw new SuperNotCalledException("Fragment " + f
- + " did not call through to super.onAttach()");
- }
- if (f.mParentFragment == null) {
- mActivity.onAttachFragment(f);
- }
- if (!f.mRetaining) {
- f.performCreate(f.mSavedFragmentState);
- }
- 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.performCreateView(f.getLayoutInflater(
- f.mSavedFragmentState), null, f.mSavedFragmentState);
- if (f.mView != null) {
- f.mView.setSaveFromParentEnabled(false);
- if (f.mHidden) f.mView.setVisibility(View.GONE);
- f.onViewCreated(f.mView, f.mSavedFragmentState);
- }
- }
- case Fragment.CREATED:
- if (newState > Fragment.CREATED) {
- if (DEBUG) Log.v(TAG, "moveto ACTIVITY_CREATED: " + f);
- if (!f.mFromLayout) {
- ViewGroup container = null;
- if (f.mContainerId != 0) {
- container = (ViewGroup)mContainer.findViewById(f.mContainerId);
- if (container == null && !f.mRestored) {
- throwException(new IllegalArgumentException(
- "No view found for id 0x"
- + Integer.toHexString(f.mContainerId) + " ("
- + f.getResources().getResourceName(f.mContainerId)
- + ") for fragment " + f));
- }
- }
- f.mContainer = container;
- f.mView = f.performCreateView(f.getLayoutInflater(
- f.mSavedFragmentState), container, f.mSavedFragmentState);
- if (f.mView != null) {
- f.mView.setSaveFromParentEnabled(false);
- if (container != null) {
- Animator anim = loadAnimator(f, transit, true,
- transitionStyle);
- if (anim != null) {
- anim.setTarget(f.mView);
- anim.start();
- }
- container.addView(f.mView);
- }
- if (f.mHidden) f.mView.setVisibility(View.GONE);
- f.onViewCreated(f.mView, f.mSavedFragmentState);
- }
- }
- f.performActivityCreated(f.mSavedFragmentState);
- if (f.mView != null) {
- f.restoreViewState(f.mSavedFragmentState);
- }
- f.mSavedFragmentState = null;
- }
- case Fragment.ACTIVITY_CREATED:
- case Fragment.STOPPED:
- if (newState > Fragment.STOPPED) {
- if (DEBUG) Log.v(TAG, "moveto STARTED: " + f);
- f.performStart();
- }
- case Fragment.STARTED:
- if (newState > Fragment.STARTED) {
- if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f);
- f.mResumed = true;
- f.performResume();
- // Get rid of this in case we saved it and never needed it.
- f.mSavedFragmentState = null;
- f.mSavedViewState = null;
- }
- }
- } else if (f.mState > newState) {
- switch (f.mState) {
- case Fragment.RESUMED:
- if (newState < Fragment.RESUMED) {
- if (DEBUG) Log.v(TAG, "movefrom RESUMED: " + f);
- f.performPause();
- f.mResumed = false;
- }
- case Fragment.STARTED:
- if (newState < Fragment.STARTED) {
- if (DEBUG) Log.v(TAG, "movefrom STARTED: " + f);
- f.performStop();
- }
- case Fragment.STOPPED:
- case Fragment.ACTIVITY_CREATED:
- if (newState < Fragment.ACTIVITY_CREATED) {
- if (DEBUG) Log.v(TAG, "movefrom ACTIVITY_CREATED: " + f);
- if (f.mView != null) {
- // Need to save the current view state if not
- // done already.
- if (!mActivity.isFinishing() && f.mSavedViewState == null) {
- saveFragmentViewState(f);
- }
- }
- f.performDestroyView();
- if (f.mView != null && f.mContainer != null) {
- Animator anim = null;
- if (mCurState > Fragment.INITIALIZING && !mDestroyed) {
- anim = loadAnimator(f, transit, false,
- transitionStyle);
- }
- if (anim != null) {
- final ViewGroup container = f.mContainer;
- final View view = f.mView;
- final Fragment fragment = f;
- container.startViewTransition(view);
- f.mAnimatingAway = anim;
- f.mStateAfterAnimating = newState;
- anim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator anim) {
- container.endViewTransition(view);
- if (fragment.mAnimatingAway != null) {
- fragment.mAnimatingAway = null;
- moveToState(fragment, fragment.mStateAfterAnimating,
- 0, 0, false);
- }
- }
- });
- anim.setTarget(f.mView);
- anim.start();
- }
- f.mContainer.removeView(f.mView);
- }
- f.mContainer = null;
- f.mView = null;
- }
- case Fragment.CREATED:
- if (newState < Fragment.CREATED) {
- if (mDestroyed) {
- if (f.mAnimatingAway != null) {
- // The fragment's containing activity is
- // being destroyed, but this fragment is
- // currently animating away. Stop the
- // animation right now - it is not needed,
- // and we can't wait any more on destroying
- // the fragment.
- Animator anim = f.mAnimatingAway;
- f.mAnimatingAway = null;
- anim.cancel();
- }
- }
- if (f.mAnimatingAway != null) {
- // We are waiting for the fragment's view to finish
- // animating away. Just make a note of the state
- // the fragment now should move to once the animation
- // is done.
- f.mStateAfterAnimating = newState;
- newState = Fragment.CREATED;
- } else {
- if (DEBUG) Log.v(TAG, "movefrom CREATED: " + f);
- if (!f.mRetaining) {
- f.performDestroy();
- }
- f.mCalled = false;
- f.onDetach();
- if (!f.mCalled) {
- throw new SuperNotCalledException("Fragment " + f
- + " did not call through to super.onDetach()");
- }
- if (!keepActive) {
- if (!f.mRetaining) {
- makeInactive(f);
- } else {
- f.mActivity = null;
- f.mParentFragment = null;
- f.mFragmentManager = null;
- }
- }
- }
- }
- }
- }
- f.mState = newState;
- }
- public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
- if (!"fragment".equals(name)) {
- return onCreateView(name, context, attrs);
- }
- String fname = attrs.getAttributeValue(null, "class");
- TypedArray a =
- context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.Fragment);
- if (fname == null) {
- fname = a.getString(com.android.internal.R.styleable.Fragment_name);
- }
- int id = a.getResourceId(com.android.internal.R.styleable.Fragment_id, View.NO_ID);
- String tag = a.getString(com.android.internal.R.styleable.Fragment_tag);
- a.recycle();
- int containerId = parent != null ? parent.getId() : 0;
- if (containerId == View.NO_ID && id == View.NO_ID && tag == null) {
- throw new IllegalArgumentException(attrs.getPositionDescription()
- + ": Must specify unique android:id, android:tag, or have a parent with an id for " + fname);
- }
- // 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 = id != View.NO_ID ? mFragments.findFragmentById(id) : null;
- if (fragment == null && tag != null) {
- fragment = mFragments.findFragmentByTag(tag);
- }
- if (fragment == null && containerId != View.NO_ID) {
- fragment = mFragments.findFragmentById(containerId);
- }
- 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 != 0 ? id : containerId;
- fragment.mContainerId = containerId;
- fragment.mTag = tag;
- fragment.mInLayout = true;
- fragment.mFragmentManager = mFragments;
- fragment.onInflate(this, attrs, fragment.mSavedFragmentState);
- mFragments.addFragment(fragment, true);
- } else if (fragment.mInLayout) {
- // A fragment already exists and it is not one we restored from
- // previous state.
- throw new IllegalArgumentException(attrs.getPositionDescription()
- + ": Duplicate id 0x" + Integer.toHexString(id)
- + ", tag " + tag + ", or parent id 0x" + Integer.toHexString(containerId)
- + " with another fragment for " + fname);
- } else {
- // This fragment was retained from a previous instance; get it
- // going now.
- fragment.mInLayout = 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);
- }
- mFragments.moveToState(fragment);
- }
- if (fragment.mView == null) {
- throw new IllegalStateException("Fragment " + fname
- + " did not create a view.");
- }
- if (id != 0) {
- fragment.mView.setId(id);
- }
- if (fragment.mView.getTag() == null) {
- fragment.mView.setTag(tag);
- }
- return fragment.mView;
- }
onAttach()
当fragment被加入到activity时调用(在这个方法中可以获得所在的activity)。
OnCreate()
创建我们的fragment
onCreateView()
当activity要得到fragment的layout时,调用此方法,fragment在其中创建自己的layout(界面)。
FragmentManager 与 FragmentTransaction
- FragmentManager fm = getFragmentManager();
- FragmentTransaction transaction = fm.beginTransaction();
- @Override
- public FragmentTransaction beginTransaction() {
- return new BackStackRecord(this);
- }
很明显我们的FragmentTransaction实际上是一个回退栈。
1、管理Fragment回退栈
类似与Android系统为Activity维护一个任务栈,我们也可以通过Activity维护一个回退栈来保存每次Fragment事务发生的变化。如果你将Fragment任务添加到回退栈,当用户点击后退按钮时,将看到上一次的保存的Fragment。一旦Fragment完全从后退栈中弹出,用户再次点击后退键,则退出当前Activity。
看这样一个效果图:
点击第一个按钮,切换到第二个界面,点击第二个按钮,切换到第三个界面,然后点击Back键依次回退。这像不像初学Android时的Activity跳转,当然了,这里肯定不是,不然我就跪了。这里是Fragment实现的,用户点击Back,实际是Fragment回退栈不断的弹栈。
如何添加一个Fragment事务到回退栈:
FragmentTransaction.addToBackStack(String)
下面讲解代码:很明显一共是3个Fragment和一个Activity.
先看Activity的布局文件:
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
- <FrameLayout
- android:id="@+id/id_content"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent" >
- </FrameLayout>
- </RelativeLayout>
MainActivity.java
- package com.zhy.zhy_fragments;
- import android.app.Activity;
- import android.app.FragmentManager;
- import android.app.FragmentTransaction;
- import android.os.Bundle;
- import android.view.Window;
- public class MainActivity extends Activity
- {
- @Override
- protected void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.activity_main);
- FragmentManager fm = getFragmentManager();
- FragmentTransaction tx = fm.beginTransaction();
- tx.add(R.id.id_content, new FragmentOne(),"ONE");
- tx.commit();
- }
- }
下面是FragmentOne
- package com.zhy.zhy_fragments;
- import android.app.Fragment;
- import android.app.FragmentManager;
- import android.app.FragmentTransaction;
- import android.os.Bundle;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.view.ViewGroup;
- import android.widget.Button;
- public class FragmentOne extends Fragment implements OnClickListener
- {
- private Button mBtn;
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState)
- {
- View view = inflater.inflate(R.layout.fragment_one, container, false);
- mBtn = (Button) view.findViewById(R.id.id_fragment_one_btn);
- mBtn.setOnClickListener(this);
- return view;
- }
- @Override
- public void onClick(View v)
- {
- FragmentTwo fTwo = new FragmentTwo();
- FragmentManager fm = getFragmentManager();
- FragmentTransaction tx = fm.beginTransaction();
- tx.replace(R.id.id_content, fTwo, "TWO");
- tx.addToBackStack(null);
- tx.commit();
- }
- }
我们在点击FragmentOne中的按钮时,使用了replace方法,如果你看了前一篇博客,一定记得replace是remove和add的合体,并且如果不添加事务到回退栈,前一个Fragment实例会被销毁。这里很明显,我们调用tx.addToBackStack(null);将当前的事务添加到了回退栈,所以FragmentOne实例不会被销毁,但是视图层次依然会被销毁,即会调用onDestoryView和onCreateView,证据就是:仔细看上面的效果图,我们在跳转前在文本框输入的内容,在用户Back得到第一个界面的时候不见了。
接下来FragmentTwo
- package com.zhy.zhy_fragments;
- import android.app.Fragment;
- import android.app.FragmentManager;
- import android.app.FragmentTransaction;
- import android.os.Bundle;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.view.ViewGroup;
- import android.widget.Button;
- public class FragmentTwo extends Fragment implements OnClickListener
- {
- private Button mBtn ;
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState)
- {
- View view = inflater.inflate(R.layout.fragment_two, container, false);
- mBtn = (Button) view.findViewById(R.id.id_fragment_two_btn);
- mBtn.setOnClickListener(this);
- return view ;
- }
- @Override
- public void onClick(View v)
- {
- FragmentThree fThree = new FragmentThree();
- FragmentManager fm = getFragmentManager();
- FragmentTransaction tx = fm.beginTransaction();
- tx.hide(this);
- tx.add(R.id.id_content , fThree, "THREE");
- // tx.replace(R.id.id_content, fThree, "THREE");
- tx.addToBackStack(null);
- tx.commit();
- }
- }
这里点击时,我们没有使用replace,而是先隐藏了当前的Fragment,然后添加了FragmentThree的实例,最后将事务添加到回退栈。这样做的目的是为了给大家提供一种方案:如果不希望视图重绘该怎么做,请再次仔细看效果图,我们在FragmentTwo的EditText填写的内容,用户Back回来时,数据还在~~~
最后FragmentThree就是简单的Toast了:
- package com.zhy.zhy_fragments;
- import android.app.Fragment;
- import android.os.Bundle;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.view.ViewGroup;
- import android.widget.Button;
- import android.widget.Toast;
- public class FragmentThree extends Fragment implements OnClickListener
- {
- private Button mBtn;
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState)
- {
- View view = inflater.inflate(R.layout.fragment_three, container, false);
- mBtn = (Button) view.findViewById(R.id.id_fragment_three_btn);
- mBtn.setOnClickListener(this);
- return view;
- }
- @Override
- public void onClick(View v)
- {
- Toast.makeText(getActivity(), " i am a btn in Fragment three",
- Toast.LENGTH_SHORT).show();
- }
- }
好了,经过上面的介绍,应该已经知道Fragment回退栈是怎么一回事了,以及hide,replace等各自的应用的场景。
这里极其注意一点:上面的整体代码不具有任何参考价值,纯粹为了显示回退栈,在后面讲解了Fragment与Activity通信以后,会重构上面的代码!
- public void run() {
- if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Run: " + this);
- if (mAddToBackStack) {
- if (mIndex < 0) {
- throw new IllegalStateException("addToBackStack() called after commit()");
- }
- }
- bumpBackStackNesting(1);
- Op op = mHead;
- while (op != null) {
- switch (op.cmd) {
- case OP_ADD: {
- Fragment f = op.fragment;
- f.mNextAnim = op.enterAnim;
- mManager.addFragment(f, false);
- } break;
- case OP_REPLACE: {
- Fragment f = op.fragment;
- if (mManager.mAdded != null) {
- /// M: it may remove mManager.mAdded items in mManager.removeFragment()
- final ArrayList<Fragment> added = new ArrayList<Fragment>(mManager.mAdded);
- for (int i=0; i<added.size(); i++) {
- Fragment old = added.get(i);
- if (FragmentManagerImpl.DEBUG) Log.v(TAG,
- "OP_REPLACE: adding=" + f + " old=" + old);
- if (f == null || old.mContainerId == f.mContainerId) {
- if (old == f) {
- op.fragment = f = null;
- } else {
- if (op.removed == null) {
- op.removed = new ArrayList<Fragment>();
- }
- op.removed.add(old);
- old.mNextAnim = op.exitAnim;
- if (mAddToBackStack) {
- old.mBackStackNesting += 1;
- if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting of "
- + old + " to " + old.mBackStackNesting);
- }
- mManager.removeFragment(old, mTransition, mTransitionStyle);
- }
- }
- }
- }
- if (f != null) {
- f.mNextAnim = op.enterAnim;
- mManager.addFragment(f, false);
- }
- } break;
- case OP_REMOVE: {
- Fragment f = op.fragment;
- f.mNextAnim = op.exitAnim;
- mManager.removeFragment(f, mTransition, mTransitionStyle);
- } break;
- case OP_HIDE: {
- Fragment f = op.fragment;
- f.mNextAnim = op.exitAnim;
- mManager.hideFragment(f, mTransition, mTransitionStyle);
- } break;
- case OP_SHOW: {
- Fragment f = op.fragment;
- f.mNextAnim = op.enterAnim;
- mManager.showFragment(f, mTransition, mTransitionStyle);
- } break;
- case OP_DETACH: {
- Fragment f = op.fragment;
- f.mNextAnim = op.exitAnim;
- mManager.detachFragment(f, mTransition, mTransitionStyle);
- } break;
- case OP_ATTACH: {
- Fragment f = op.fragment;
- f.mNextAnim = op.enterAnim;
- mManager.attachFragment(f, mTransition, mTransitionStyle);
- } break;
- default: {
- throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
- }
- }
- op = op.next;
- }
- mManager.moveToState(mManager.mCurState, mTransition,
- mTransitionStyle, true);
- if (mAddToBackStack) {
- mManager.addBackStackState(this);
- }
- }
通过上面的switch,最终我们的fragment状态切换交给了我们FragmentManager
- public void removeFragment(Fragment fragment, int transition, int transitionStyle) {
- ............
- mAdded.remove(fragment);
- ..........
- }
- public void hideFragment(Fragment fragment, int transition, int transitionStyle) {
- ..............
- finalFragment.mView.setVisibility(View.GONE);
- .............
- }
- public void showFragment(Fragment fragment, int transition, int transitionStyle) {
- ...........
- fragment.mView.setVisibility(View.VISIBLE);
- .........
- }
- public void addFragment(Fragment fragment, boolean moveToStateNow) {
- .............
- mAdded.add(fragment);
- .......
- }
- transaction.hide(mFragment);
- transaction.show(mFragment);
- transaction.remove(mFragment);
- transaction.add(mFragment);
- transaction.replace(<span style="color: rgb(68, 68, 68); font-family: Consolas, 'Courier New', Courier, mono, serif; line-height: 17.98611068725586px;">R.id.id_content,</span>mFragment);
- <span style="color: rgb(51, 51, 51);"> case OP_REPLACE: {
- Fragment f = op.fragment;
- if (mManager.mAdded != null) {
- /// M: it may remove mManager.mAdded items in mManager.removeFragment()
- final ArrayList<Fragment> added = new ArrayList<Fragment>(mManager.mAdded);
- for (int i=0; i<added.size(); i++) {
- Fragment old = added.get(i);
- if (FragmentManagerImpl.DEBUG) Log.v(TAG,
- "OP_REPLACE: adding=" + f + " old=" + old);
- if (f == null || old.mContainerId == f.mContainerId) {
- if (old == f) {
- op.fragment = f = null;
- } else {
- if (op.removed == null) {
- op.removed = new ArrayList<Fragment>();
- }
- op.removed.add(old);
- old.mNextAnim = op.exitAnim;
- if (mAddToBackStack) {
- old.mBackStackNesting += 1;
- if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting of "
- + old + " to " + old.mBackStackNesting);
- }
- </span><span style="color:#ff0000;">mManager.removeFragment(old, mTransition, mTransitionStyle);</span><span style="color:#333333;">
- }
- }
- }
- }
- if (f != null) {
- f.mNextAnim = op.enterAnim;
- </span><span style="color:#ff0000;">mManager.addFragment(f, false);</span><span style="color:#333333;">
- }
- } break;</span>