[Android]Fragment源码分析(二) 状态

我们上一讲,抛出来一个问题,就是当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源码分析(二) 状态

时间: 2024-10-27 09:27:01

[Android]Fragment源码分析(二) 状态的相关文章

[Android]Fragment源码分析(一) 构造

Fragment是Android3.0之后提供的api,被大家广泛所熟知的主要原因还是因为随即附带的ViewPager控件.虽然我并不喜欢用它,但是它确实是一个相对不错的控件.还是我的一贯作风,我将从源码上向大家展示什么是Fragment.我们先写一个简单的代码对Fragment有个直观的认识:(为了保证我们方便调试,我们可以直接使用V4提供的源码包) FragmentTransaction t = getSupportFragmentManager().beginTransaction();

[Android]Fragment源码分析(三) 事务

Fragment管理中,不得不谈到的就是它的事务管理,它的事务管理写的非常的出彩.我们先引入一个简单常用的Fragment事务管理代码片段: FragmentTransaction ft = this.getSupportFragmentManager().beginTransaction(); ft.add(R.id.fragmentContainer, fragment, "tag"); ft.addToBackStack("<span style="fo

[Android]Volley源码分析(二)Cache

Cache作为Volley最为核心的一部分,Volley花了重彩来实现它.本章我们顺着Volley的源码思路往下,来看下Volley对Cache的处理逻辑. 我们回想一下昨天的简单代码,我们的入口是从构造一个Request队列开始的,而我们并不直接调用new来构造,而是将控制权反转给Volley这个静态工厂来构造. com.android.volley.toolbox.Volley: public static RequestQueue newRequestQueue(Context conte

[Android]Fragment源码分析(肆) Fragment栈管理

Fragment的栈是Fragment管理颇为出彩的一部分,它跟Activity栈的本质差异除了在数据结构上和逻辑上的不同之外,主要区别还在于: 1.Fragment管理是在进程空间内的 2.Fragment的管理一般情况下是一个Window下进行的. Fragment的管理在一个进程空间内是比较好理解的,因为我们知道Activity的管理其实相对复杂,它的管理是通过IPC调用,IPC的一端是我们的Client,而作为Server的是Ams服务.Activity的管理是基于Window的,而Fr

[Android]Volley源码分析(二)

上一篇介绍了Volley的使用,主要接触了Request与RequestQueue这两个类,这篇就来了解一下这两个类的具体实现. Request类图: Request类: Request是一个抽象类,其中的主要属性: mMethod: 请求方法,目前支持GET, POST, PUT, DELETE, HEAD, OPTIONS,TRACE, PATCH方法 mUrl: 请求Url mErrorListener: 错误处理监听器,请求出错时调用 mSequence: 请求的序号,相同优先级的请求在

Android Launcher2源码分析

Android   Launcher2源码分析 Android源码程序程序中有一个应用程序入口,官方给出的中文翻译为"启动器".我们一下统称Launcher. Launcher源码分析,我们还是从AndroidManifest.xml开始: <application android:name="com.android.launcher2.LauncherApplication" android:label="@string/application_n

[Android]Volley源码分析(四)

上篇中有提到NetworkDispatcher是通过mNetwork(Network类型)来进行网络访问的,现在来看一下关于Network是如何进行网络访问的. Network部分的类图: Network有一个实现类BasicNetwork,它有一个mHttpStack的属性,实际的网络请求是由这个mHttpStack来进行的,看BasicNetwork的performRequest()方法, 1 @Override 2 public NetworkResponse performRequest

baksmali和smali源码分析(二)

这一节,主要介绍一下 baksmali代码的框架. 我们经常在反编译android apk包的时候使用apktool这个工具,其实本身这个工具里面对于dex文件解析和重新生成就是使用的baksmali 和smali这两个jar包其中 baksmali是将 dex文件转换成便于阅读的smali文件的,具体使用命令如下:java -jar baksmali.jar classes.dex -o myout其中myout是输出的文件夹 而smali是将smali文件重新生成回 dex文件的具体使用的命

【梦幻连连连】源码分析(二)

转载请注明出处:http://blog.csdn.net/oyangyufu/article/details/24736711 GameLayer场景界面效果: 源码分析: GameLayer场景初始化,主要是初始化加载界面及背景音乐 bool GameLayer::init() { float dt=0.0f; if ( !CCLayerColor::initWithColor(ccc4(255, 255, 255, 255))) { return false; } this->initLoa