[Android]Fragment源碼分析(二) 狀態,androidfragment

來源:互聯網
上載者:User

[Android]Fragment源碼分析(二) 狀態,androidfragment

我們上一講,拋出來一個問題,就是當Activity的onCreateView的時候,是如何構造Fragment中的View參數。要回答這個問題我們先要瞭解Fragment的狀態,這是Fragment管理中非常重要的一環。我們先來看一下FragmentActivity提供的一些核心回調:

@Override    protected void onCreate(Bundle savedInstanceState) {        mFragments.attachActivity(this, mContainer, null);        // Old versions of the platform didn't do this!        if (getLayoutInflater().getFactory() == null) {            getLayoutInflater().setFactory(this);        }        super.onCreate(savedInstanceState);....        mFragments.dispatchCreate();    }
我們跟入mFragments.dispatchCreate方法中:

public void dispatchCreate() {        mStateSaved = false;        moveToState(Fragment.CREATED, false);    }

我們看到,對於FragmentManager來說,做了一次狀態轉換。我上一篇說過FragmentManager是及其重要的類,它承擔了Fragment管理最為核心的工作。它有它自身的狀態機器,而它的狀態,可以理解為與Activity本身基本同步。

在Fm裡面維護自己的一個狀態,當你匯入一個Fragment的時候,Fm的目的,就是為了讓Fragment和自己的狀態基本保持一致.

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();                    }                }            }            ...        }    }

我們看到,FragmentManager的每一次狀態變更,都會引起mActive裡面的Fragment的狀態變更。而mActive是所有納入FragmentManager管理的Fragment容器。我們來看一下Fragment的幾個狀態:

static final int INITIALIZING = 0;     // Not yet created.    static final int CREATED = 1;          // Created.    static final int ACTIVITY_CREATED = 2; // The activity has finished its creation.    static final int STOPPED = 3;          // Fully created, not started.    static final int STARTED = 4;          // Created and started, not resumed.    static final int RESUMED = 5;          // Created started and resumed.

可以看出實際上,你的狀態越靠後你的狀態值越大,實際上在Fm的管理中,也巧妙的用到了這一點。

 if (f.mState < newState) {  ...} else {  ...}

對於f.mState<newState可以理解為創造的過程。同時我們也能找到我們上一篇文章的問題的答案:

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.mInnerView = f.mView;                        f.mView = NoSaveStateFrameLayout.wrap(f.mView);                        if (f.mHidden)                            f.mView.setVisibility(View.GONE);                        f.onViewCreated(f.mView, f.mSavedFragmentState);                    } else {                        f.mInnerView = null;                    }                }

f.mFromLayout代表的是你這個Fragment的產生是否是從layout.xml檔案中產生的。而它的View的產生是調用performCreateView來產生的。

View performCreateView(LayoutInflater inflater, ViewGroup container,            Bundle savedInstanceState) {        if (mChildFragmentManager != null) {            mChildFragmentManager.noteStateNotSaved();        }        return onCreateView(inflater, container, savedInstanceState);    }

對,這裡就是我們非常熟悉的onCreateView回調的出處。當然我們現在還是屬於Fragment.INITIALIZING這個狀態。但實際上,我們在調用Fragment的時候FragmentManageer已經進入了Create狀態。也就是說newState參數應該是Create才對。所以我們接著代碼往下走:

 case Fragment.CREATED:                if (newState > Fragment.CREATED) {                    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.mInnerView = f.mView;                            f.mView = NoSaveStateFrameLayout.wrap(f.mView);                            if (container != null) {                                Animation anim = loadAnimation(f, transit,                                        true, transitionStyle);                                if (anim != null) {                                    f.mView.startAnimation(anim);                                }                                container.addView(f.mView);                            }                            if (f.mHidden)                                f.mView.setVisibility(View.GONE);                            f.onViewCreated(f.mView, f.mSavedFragmentState);                        } else {                            f.mInnerView = null;                        }                    }                    f.performActivityCreated(f.mSavedFragmentState);                    if (f.mView != null) {                        f.restoreViewState(f.mSavedFragmentState);                    }                    f.mSavedFragmentState = null;                }
我們看到實際上這段代碼是對FragmentManager狀態是Create以上狀態且Fragment的匯入並不是採用layout.xml方式匯入的處理。這是為什麼呢?因為在onCreate之後,基本上你的控制項已經在Create狀態的時候產生的差不多了,你所要做的就是在產生的控制項中找到Fragment對應的容器,然後裝入你的控制項。同時,我們也看到了對Fragment的動畫處理:

if (f.mView != null) {                            f.mInnerView = f.mView;                            f.mView = NoSaveStateFrameLayout.wrap(f.mView);                            if (container != null) {                                Animation anim = loadAnimation(f, transit,                                        true, transitionStyle);                                if (anim != null) {                                    f.mView.startAnimation(anim);                                }                                container.addView(f.mView);                            }                            if (f.mHidden)                                f.mView.setVisibility(View.GONE);                            f.onViewCreated(f.mView, f.mSavedFragmentState);                        } else {                            f.mInnerView = null;                        }
而這種動畫的處理和參數的配置,我們留到後面講到Fragment事務的時候再說。




Android fragment使用中遇到的問題?

把gridview的fragment的布局和gridview的item的布局貼出來看看。
 
android的Fragment切換時怎儲存狀態,避免重複調用onCreateView()

在sdk sample的APIdemo 的FragmentHideShow.java
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.