get${XXX}FragmentManager()的区别

${XXX}


为何会有这么多get${XXX}FragmentManager,它们存在目的是什么呢

FragmentActivity

  • getSupportFragmentManager
  • getFragmentManager

Fragment

  • getFragmentManager
  • getChildFragmentManager

FragmentActivity.getSupportFragmentManager()


代码取自 v4兼容包

    /**
     * Return the FragmentManager for interacting with fragments associated
     * with this activity.
     */
    public FragmentManager getSupportFragmentManager() {
        return mFragments.getSupportFragmentManager();
    }

跟进mFragments看到

final FragmentController mFragments = FragmentController.createController(new HostCallbacks());

继续跟进FragmentControllerFragmentController的方法列表如下:

/** Attaches the host to the FragmentManager for this controller. The host must be attached before the FragmentManager can be used to manage Fragments.*/
attachHost 
createController
/**dispatch fragment lifecycle */
onCreateView
dispatchActivityCreated
dispatchConfigurationChanged
dispatchContextItemSelected
dispatchCreate
dispatchCreateOptionsMenu
dispatchDestroy
dispatchDestroyView
dispatchLowMemory
dispatchOptionsItemSelected
dispatchOptionsMenuClosed
dispatchPause
dispatchPrepareOptionsMenu
dispatchReallyStop
dispatchResume
dispatchStart
dispatchStop
/**dispatch loader*/
doLoaderDestroy
doLoaderRetain
doLoaderStart
doLoaderStop
dumpLoaders
reportLoaderStart
restoreLoaderNonConfig
retainLoaderNonConfig
/**Execute any pending actions for the Fragments managed by the controller's FragmentManager.
Call when queued actions can be performed [eg when the Fragment moves into a start or resume state].*/
execPendingActions
getActiveFragments
getActiveFragmentsCount
/**Returns a {@link FragmentManager} for this controller.*/
getSupportFragmentManager
/**Returns a {@link LoaderManager}.*/
getSupportLoaderManager
/**Bundle state manager*/
noteStateNotSaved
restoreAllState
retainNonConfig
saveAllState
/**
Provides integration points with a FragmentManager for a fragment host.
It is the responsibility of the host to take care of the Fragment's lifecycle. The methods provided by FragmentController are for that purpose.
*/
class FragmentController{
    private final FragmentHostCallback<?> mHost;
    // ignore ...
}

查看源代码之后,FragmentController做了如下几件事情:

  1. 提供单例方法createController用于创建实例;
  2. 提供attachHost(Fragment parent),通过FragmentControllerHostFragmentFragmentContainer附加到FragmentManager
  3. 提供分发Fragment 的生命周期的方法;
  4. 提供存储/恢复SaveState的方法,用于处理Fragment的状态恢复;
  5. 提供分发LoaderMananger的回调方法;

接着跟进FragmentHostCallback,查看继承关系如下:

/**
Integration points with the Fragment host.Fragments may be hosted by any object; such as an Activity.

In order to host fragments, implement FragmentHostCallback, overriding the methods applicable to the host.*/
--Object (java.lang)
----FragmentContainer (android.support.v4.app)
------FragmentHostCallback (android.support.v4.app)
--------HostCallbacks in FragmentActivity (android.support.v4.app)

FragmentHostCallback存在的意义,上面的注释中已经说明的很明白了,那么继续跟进它在FragmentActivity中的 usage。

final FragmentController mFragments = FragmentController.createController(new HostCallbacks());

OK,FragmentController 已经清晰的展示它的职责。


那么继续回到代码:

public FragmentManager getSupportFragmentManager() {
        return mFragments.getSupportFragmentManager();
}

跟进FragmentHostCallback

final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();

FragmentManagerImpl getFragmentManagerImpl() {
        return mFragmentManager;
    }

继续跟进FragmentManagerImpl

Object (java.lang)
--FragmentManager (android.support.v4.app)
----FragmentManagerImpl (android.support.v4.app)

愈来愈接近FragmentManager( 对 FragmentManager 不了解?点我!)。我们了解到FragmentManager只是一个抽象类,实际的实现类只有FragmentManagerImpl一个而已。

先不慌忙,先啃掉FragmentManagerImpl再回头看看为什么。

// Read The Fuck Code!(RTFC)
// 已忽略掉无关的代码
final class FragmentManagerImpl extends FragmentManager implements LayoutInflaterFactory {

    /** 一个pending 列表,借助 handler 将 Runnable 转发到execPendingActions()中。在execPendingActions()经由中转 Runnable 执行任务。*/
    ArrayList<Runnable> mPendingActions;

    /**{@link #moveToState()}*/
    int mCurState = Fragment.INITIALIZING;
    /**{@link FragmentController#attachController()}*/
    FragmentHostCallback mHost;
    FragmentController mController;
    FragmentContainer mContainer;
    Fragment mParent;

    Runnable mExecCommit = new Runnable() {
        @Override
        public void run() {
            execPendingActions();
        }
    }

    @Override
    public boolean executePendingTransactions() {
        return execPendingActions();
    }

    @Override
    public FragmentTransaction beginTransaction() {
        // BackStackRecord 简要说就是记录“你从哪里来,到哪里去。”
        // 如:你从 A 处来,要去往 B处。
        // 记录的是:这个事务(从 A 来,要去 B。),而不是目的{A,B}。
        // 具体,可以跟进{@link BackStackRecord}
        return new BackStackRecord(this);
    }
   @Override
    public void popBackStack() {
        enqueueAction(new Runnable() {
            @Override public void run() {
                popBackStackState(mHost.getHandler(), null, -1, 0);
            }
        }, false);
    }

@Override
    public boolean popBackStackImmediate() {
        checkStateLoss();
        executePendingTransactions();
        return popBackStackState(mHost.getHandler(), null, -1, 0);
    }

    @Override
    public int getBackStackEntryCount() {
        return mBackStack != null ? mBackStack.size() : 0;
    }

     /**
     *增加了一个action,等待队列的操作。
     * @param action 待添加的行为
     * @param allowStateLoss 是否允许丢失状态
     * @throws IllegalStateException if the activity has been destroyed
     */
    public void enqueueAction(Runnable action, boolean allowStateLoss) {
        if (!allowStateLoss) {
            checkStateLoss();
        }
        synchronized (this) {
            if (mDestroyed || mHost == null) {
                throw new IllegalStateException("Activity has been destroyed");
            }
            if (mPendingActions == null) {
                mPendingActions = new ArrayList<Runnable>();
            }
            mPendingActions.add(action);
            if (mPendingActions.size() == 1) {
                mHost.getHandler().removeCallbacks(mExecCommit);
                mHost.getHandler().post(mExecCommit);
            }
        }
    }

public boolean execPendingActions() {
      //...
      while (true) {
            int numActions;

            synchronized (this) {
                if (mPendingActions == null || mPendingActions.size() == 0) {
                    break;
                }

                numActions = mPendingActions.size();
                if (mTmpActions == null || mTmpActions.length < numActions) {
                    mTmpActions = new Runnable[numActions];
                }
                mPendingActions.toArray(mTmpActions);
                mPendingActions.clear();
                mHost.getHandler().removeCallbacks(mExecCommit);
            }

            mExecutingActions = true;
            for (int i=0; i<numActions; i++) {
                mTmpActions[i].run();
                mTmpActions[i] = null;
            }
            mExecutingActions = false;
            didSomething = true;
        }
            //...
}

/** 对 Fragment 的状态分发的管理的实现,调用可参考{@link FragmentController#dispatch${XXX}};这个方法所做的事情是,根据状态等一系列参数,让fragment 做出对应的实现。*/
void moveToState(Fragment f, int newState, int transit, int transitionStyle,
            boolean keepActive) {
            // 有兴趣的可行阅读代码
    }
}

先总结下FragmentManagerImpl做了哪些事情?

1.BackStackRecord管理,派生于(FragmentTransaction),然最终是对 BackStackRecord.Op的管理。
2.Fragment状态的管理。


Fragment.getFragmentManager()

public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener {
    // The fragment manager we are associated with.  Set as soon as the
    // fragment is used in a transaction; cleared after it has been removed
    // from all transactions.
    FragmentManagerImpl mFragmentManager;
    // Private fragment manager for child fragments inside of this one.
    FragmentManagerImpl mChildFragmentManager;

    final public FragmentManager getFragmentManager() {
        return mFragmentManager;
    }
    /**
     * Return a private FragmentManager for placing and managing Fragments
     * inside of this Fragment.
     */
    final public FragmentManager getChildFragmentManager() {
        if (mChildFragmentManager == null) {
            instantiateChildFragmentManager();
            if (mState >= RESUMED) {
                mChildFragmentManager.dispatchResume();
            } else if (mState >= STARTED) {
                mChildFragmentManager.dispatchStart();
            } else if (mState >= ACTIVITY_CREATED) {
                mChildFragmentManager.dispatchActivityCreated();
            } else if (mState >= CREATED) {
                mChildFragmentManager.dispatchCreate();
            }
        }
        return mChildFragmentManager;
    }
}

最终都是引用FragmentManagerImpl,证明他们并无分别。所以调用enableDebugLogging方法,无论调用 get${XXX}FragmentManager均会打印日志。

public abstract class FragmentManager {
/**
     * Control whether the framework's internal fragment manager debugging
     * logs are turned on.  If enabled, you will see output in logcat as
     * the framework performs fragment operations.
     */
    public static void enableDebugLogging(boolean enabled) {
        FragmentManagerImpl.DEBUG = enabled;
    }
}

getChildFragmentManagergetFragmentManager的区别有二。

  1. 不同的 instance;
  2. 增加对其持有的 fragment 的lifecycle 的更新;

附上日志:

描述了:从 ViewPager内部的 Fragment点击跳转到新的 Fragment,并点击返回的过程。

Tip:

ViewPager使用getChildFragmentManager,如果换成getFragmentManager。那么 点击返回的时候 viewPager 所持有的 Fragment 是得不到生命周期调用的,所以往往点击返回 后是显示空白的页面。注意日志中ViewPagerChildFragmentmovefrom部分。




FragmentManager: Commit: BackStackEntry{28cbf0d0}
******FragmentManager:   mName=null mIndex=-1 mCommitted=false
******FragmentManager:   Operations:
******FragmentManager:     Op #0: REPLACE DetailFragment{28cbf278 id=0x7f0c0050}
FragmentManager: Setting back stack index 1 to BackStackEntry{28cbf0d0}
FragmentManager: Run: BackStackEntry{28cbf0d0 #1}
FragmentManager: Bump nesting in BackStackEntry{28cbf0d0 #1} by 1
FragmentManager: Bump nesting of DetailFragment{28cbf278 id=0x7f0c0050} to 1
FragmentManager: OP_REPLACE: adding=DetailFragment{28cbf278 id=0x7f0c0050} old=DispatchFragment{28c8e800 #0 id=0x7f0c0050}
FragmentManager: Bump nesting of DispatchFragment{28c8e800 #0 id=0x7f0c0050} to 2
FragmentManager: remove: DispatchFragment{28c8e800 #0 id=0x7f0c0050} nesting=2
FragmentManager: movefrom RESUMED: DispatchFragment{28c8e800 #0 id=0x7f0c0050}
FragmentManager: movefrom RESUMED: ViewPagerChildFragment{28cb1038 #0 id=0x7f0c0051}
FragmentManager: movefrom RESUMED: ViewPagerChildFragment{28cb1120 #1 id=0x7f0c0051}
FragmentManager: movefrom STARTED: DispatchFragment{28c8e800 #0 id=0x7f0c0050}
FragmentManager: movefrom STARTED: ViewPagerChildFragment{28cb1038 #0 id=0x7f0c0051}
FragmentManager: movefrom STARTED: ViewPagerChildFragment{28cb1120 #1 id=0x7f0c0051}
FragmentManager: movefrom STOPPED: DispatchFragment{28c8e800 #0 id=0x7f0c0050}
FragmentManager: movefrom STOPPED: ViewPagerChildFragment{28cb1038 #0 id=0x7f0c0051}
FragmentManager: movefrom STOPPED: ViewPagerChildFragment{28cb1120 #1 id=0x7f0c0051}
FragmentManager: movefrom ACTIVITY_CREATED: DispatchFragment{28c8e800 #0 id=0x7f0c0050}
FragmentManager: movefrom ACTIVITY_CREATED: ViewPagerChildFragment{28cb1038 #0 id=0x7f0c0051}
FragmentManager: movefrom ACTIVITY_CREATED: ViewPagerChildFragment{28cb1120 #1 id=0x7f0c0051}
FragmentManager: add: DetailFragment{28cbf278 id=0x7f0c0050}
FragmentManager: Allocated fragment index DetailFragment{28cbf278 #1 id=0x7f0c0050}
FragmentManager: moveto CREATED: DetailFragment{28cbf278 #1 id=0x7f0c0050}
FragmentManager: moveto ACTIVITY_CREATED: DetailFragment{28cbf278 #1 id=0x7f0c0050}
FragmentManager: moveto STARTED: DetailFragment{28cbf278 #1 id=0x7f0c0050}
FragmentManager: moveto RESUMED: DetailFragment{28cbf278 #1 id=0x7f0c0050}
FragmentManager: popFromBackStack: BackStackEntry{28cbf0d0 #1}
******FragmentManager:   mName=null mIndex=1 mCommitted=true
******FragmentManager:   Operations:
******FragmentManager:     Op #0: REPLACE DetailFragment{28cbf278 #1 id=0x7f0c0050}
******FragmentManager:       Removed: DispatchFragment{28c8e800 #0 id=0x7f0c0050}
FragmentManager: Bump nesting in BackStackEntry{28cbf0d0 #1} by -1
FragmentManager: Bump nesting of DetailFragment{28cbf278 #1 id=0x7f0c0050} to 0
FragmentManager: Bump nesting of DispatchFragment{28c8e800 #0 id=0x7f0c0050} to 1
FragmentManager: remove: DetailFragment{28cbf278 #1 id=0x7f0c0050} nesting=0
FragmentManager: movefrom RESUMED: DetailFragment{28cbf278 #1 id=0x7f0c0050}
FragmentManager: movefrom STARTED: DetailFragment{28cbf278 #1 id=0x7f0c0050}
FragmentManager: movefrom STOPPED: DetailFragment{28cbf278 #1 id=0x7f0c0050}
FragmentManager: movefrom ACTIVITY_CREATED: DetailFragment{28cbf278 #1 id=0x7f0c0050}
FragmentManager: movefrom CREATED: DetailFragment{28cbf278 #1 id=0x7f0c0050}
FragmentManager: Freeing fragment index DetailFragment{28cbf278 #1 id=0x7f0c0050}
FragmentManager: add: DispatchFragment{28c8e800 #0 id=0x7f0c0050}
FragmentManager: moveto ACTIVITY_CREATED: DispatchFragment{28c8e800 #0 id=0x7f0c0050}
FragmentManager: moveto ACTIVITY_CREATED: ViewPagerChildFragment{28cb1038 #0 id=0x7f0c0051}
FragmentManager: moveto ACTIVITY_CREATED: ViewPagerChildFragment{28cb1120 #1 id=0x7f0c0051}
FragmentManager: moveto STARTED: DispatchFragment{28c8e800 #0 id=0x7f0c0050}
FragmentManager: moveto STARTED: ViewPagerChildFragment{28cb1038 #0 id=0x7f0c0051}
FragmentManager: moveto STARTED: ViewPagerChildFragment{28cb1120 #1 id=0x7f0c0051}
FragmentManager: moveto RESUMED: DispatchFragment{28c8e800 #0 id=0x7f0c0050}
FragmentManager: moveto RESUMED: ViewPagerChildFragment{28cb1038 #0 id=0x7f0c0051}
FragmentManager: moveto RESUMED: ViewPagerChildFragment{28cb1120 #1 id=0x7f0c0051}
FragmentManager: Freeing back stack index 1


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值