http://www.binkery.com/archives/492.html
Fragment的创建
在Fragment的回调中 onCreateView
我们会初始化一个view 并 reture.
如下,我们reture的 myView 会被保存到Fragment中
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View myView = new MineView(getActivity());
return myView;
}
来看fragment的成员变量,那么可以猜想mView就是 onCreateView 所返回的,那么这个mView是怎么赋值的呢,我们继续追源码
// The parent container of the fragment after dynamically added to UI.
ViewGroup mContainer;
// The View generated for this fragment.
View mView;
// The real inner view that will save/restore state.
View mInnerView;
我们进入的源码中看Fragment中的onCreateView方法是 performCreateView
调用了
View performCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (mChildFragmentManager != null) {
mChildFragmentManager.noteStateNotSaved();
}
return onCreateView(inflater, container, savedInstanceState);
}
但是在Fragment中 并没有地方去调用 performCreateView
,跟fragment有关的 无非就是 FragmentManager
,所以我们去 FragmentManager
中找, 果然发现 mView
就是我们猜想的那样
f.mContainer = container;
f.mView = f.performCreateView(f.getLayoutInflater(
f.mSavedFragmentState), container, f.mSavedFragmentState);
Fragment的隐藏和显示
通常我们显示或隐藏Fragment
是通过如下的方式
((FragmentActivity) getContext()).getSupportFragmentManager().beginTransaction().show(mFragmentAt).commitAllowingStateLoss();
((FragmentActivity) getContext()).getSupportFragmentManager().beginTransaction().hide(mFragmentB).commitAllowingStateLoss();
我们追进 commitAllowingStateLoss
看做了什么
public int commitAllowingStateLoss() {
return commitInternal(true);
}
int commitInternal(boolean allowStateLoss) {
if (mCommitted) throw new IllegalStateException("commit already called");
if (FragmentManagerImpl.DEBUG) {
Log.v(TAG, "Commit: " + this);
LogWriter logw = new LogWriter(TAG);
PrintWriter pw = new PrintWriter(logw);
dump(" ", null, pw, null);
}
mCommitted = true;
if (mAddToBackStack) {
mIndex = mManager.allocBackStackIndex(this);
} else {
mIndex = -1;
}
mManager.enqueueAction(this, allowStateLoss);
return mIndex;
}
继续
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);
}
}
}
有用的操作就是 post(mExecCommit) , 继续
Runnable mExecCommit = new Runnable() {
@Override
public void run() {
execPendingActions();
}
};
execPendingActions中有用的操作是 startPendingDeferredFragments(); 继续追 performPendingDeferredStart
public void performPendingDeferredStart(Fragment f) {
if (f.mDeferStart) {
if (mExecutingActions) {
// Wait until we're done executing our pending transactions
mHavePendingDeferredStart = true;
return;
}
f.mDeferStart = false;
moveToState(f, mCurState, 0, 0, false);
}
}
终于到关键方法了,moveToState
是处理Fragment状态的
继续读代码我们可以看到
if (f.mHidden) f.mView.setVisibility(View.GONE);
f.onViewCreated(f.mView, f.mSavedFragmentState);
由此可看hide()的基本原理就是 将Fragment的 mView 不可见
小注 : 如果我们在hide(mFragmentB)之后 ,手动将 mFragmentB的view.setVisible(View.Visible); 的话,会导致hide失效 。