Android开发艺术探索学习-Activity跳转时的生命周期

前言:在阅读《Android开发艺术探索》中,关于Activity生命周期的介绍中,作者提出了一个问题: “假设当前Activity为A,如果这时用户打开一个新ActivityB,那么B的onResume和A的onPause哪个先执行呢?”。看到这个问题,当时立马倍感亲切,因为自己在面试过程中就被问到这个问题。当时虽然是答对的结果,但是要分析原因的时候就如哏在喉。所以借着这个机会结合源码好好分析下。

    其实分析这个问题,肯定是要涉及到Activity的启动过程,以前也看过相关的文章,说实话很难记住重点。那么这里我结合阅读《Android开发艺术探索》的心得总结下。

    分析该问题需要涉及到的类有Instrumentation、ActivityManagerService、ActivityThread、ActivityStack、ActivityStackSupervisor、ApplicationThread等。Instrumentation这类对我来说似曾相识啊,因为以前做单元测试的时候经常见过,为啥Activity启动会与它有关呢?这个具体原因等到学习了Activity启动过程再分析吧。不过这里查看了下Instrumentation的源码关于它的介绍如下:
    Base class for implementing application instrumentation code. When running with instrumentation turned on, this class will be instantiated for you before any of the application code, allowing you to monitor all of the interaction the system has with the application. An Instrumentation implementation is described to the system through an AndroidManifest.xml's <instrumentation> tag.
大概的意思是:该类是实现Application instrumentation代码的基类,当应用处于运行态且 instrumentation是开启状态,那么该类 能够在应用代码任意位置之前进行实例化,可以监控应用与系统的所有交互的行为。 instrumentation的可以通过AndroidManifest.xml中的< instrumentation >标签进行实现。
    启动Activity的请求会由 instrumentation处理,查看源码发现 instrumentation中有newActivity和newApplication方法。

newActivity代码如下:
/**
     * Perform instantiation of the process's {@link Activity} object.  The
     * default implementation provides the normal system behavior.
     *

     * @param cl The ClassLoader with which to instantiate the object.
     * @param className The name of the class implementing the Activity
     *                  object.
     * @param intent The Intent object that specified the activity class being
     *               instantiated.
     *

     * @return The newly instantiated Activity object.
     */
    public Activity newActivity(ClassLoader cl, String className,
            Intent intent)
            throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
        return (Activity)cl.loadClass(className).newInstance();
    }
可以看到Activity是通过类加载器加载出来的,原来不是new出来的。稍微了解了下 instrumentation类,继续回到正题。启动Activity的请求由 instrumentation来处理,然后它通过binder向ActivityManagerService发请求,AMS内部维护一个ActivityStack并负责栈内的Activity同步状态,AMS通过ActivityThread去同步Activity的状态从而完成生命周期方法的调用。
     ActivityStack顾名思义是管理Activity的栈,源码的描述其作用也很简单地使用了一句话: State and management of a single stack of activities。在ActivityStack中有三个方法:

resumeTopActivityLocked(ActivityRecord prev )代码如下:
/**
     * Ensure that the top activity in the stack is resumed.
     *
     * @param prev The previously resumed activity, for when in the process
     * of pausing; can be null to call from elsewhere.
     *
     * @return Returns true if something is being resumed, or false if
     * nothing happened.
     */
    final boolean resumeTopActivityLocked(ActivityRecord prev) {
        return resumeTopActivityLocked(prev, null);
    }
该方法的作用是确保栈顶的Activity已经是resumed状态。
在resumeTopActivityLocked(ActivityRecord prev, Bundle options)方法中调用了 resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options)方法,在resumeTopActivityInnerLocked方法中有这么一段代码:
        // We need to start pausing the current activity so the top one
        // can be resumed...
        boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0;
        boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
        if (mResumedActivity != null) {
            pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
            if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Pausing " + mResumedActivity);
        }
从该段代码可知:当前栈顶的Activity需要onPause之后,新的Activity才能启动。接着在ActivityStackSupervisor中的 realStartActivityLocked方法中调用如下代码:
            app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info, 
                    new Configuration(mService.mConfiguration),
                    r.compat, r.task.voiceInteractor, app.repProcState, r.icicle, r.persistentState,
                    results, newIntents, !andResume, mService.isNextTransitionForward(),
                    profilerInfo);
ActivityStackSupervisor类是4.4版本之后加入的,用于增加对栈的管理。查看其源码中的方法可以看到很多方法都有与Stack有关。
app.thread的类型是IApplicationThread,其具体实现是ActivityThread类中ApplicationThread,所以该方法实际是调用到Application中的scheduleLaunchActivity方法,在该方法中最终会完成Activity的onCreate、onStart、onResume的调用过程。
scheduleLaunchActivity中调用了 sendMessage(H. LAUNCH_ACTIVITY , r ),继续追踪代码可以看到在H(Handler)中最终调用了 handleLaunchActivity( r , null );这个方法是最关键的方法,所以展示下其源码:
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();
        mSomeActivitiesChanged = true;

        if (r.profilerInfo != null) {
            mProfiler.setProfiler(r.profilerInfo);
            mProfiler.startProfiling();
        }

        // Make sure we are running with the most recent config.
        handleConfigurationChanged(null, null);

        if (localLOGV) Slog.v(
            TAG, "Handling launch of " + r);
        //这里Activity被创建起来了,其onCreate和onStart会被调用
        Activity a = performLaunchActivity(r, customIntent);

        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            Bundle oldState = r.state;
        //这里Activity的onResume会被调用
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed);

            if (!r.activity.mFinished && r.startsNotResumed) {
                // The activity manager actually wants this one to start out
                // paused, because it needs to be visible but isn't in the
                // foreground.  We accomplish this by going through the
                // normal startup (because activities expect to go through
                // onResume() the first time they run, before their window
                // is displayed), and then pausing it.  However, in this case
                // we do -not- need to do the full pause cycle (of freezing
                // and such) because the activity manager assumes it can just
                // retain the current state it has.
                try {
                    r.activity.mCalled = false;
                    mInstrumentation.callActivityOnPause(r.activity);
                    // We need to keep around the original state, in case
                    // we need to be created again.  But we only do this
                    // for pre-Honeycomb apps, which always save their state
                    // when pausing, so we can not have them save their state
                    // when restarting from a paused state.  For HC and later,
                    // we want to (and can) let the state be saved as the normal
                    // part of stopping the activity.
                    if (r.isPreHoneycomb()) {
                        r.state = oldState;
                    }
                    if (!r.activity.mCalled) {
                        throw new SuperNotCalledException(
                            "Activity " + r.intent.getComponent().toShortString() +
                            " did not call through to super.onPause()");
                    }

                } catch (SuperNotCalledException e) {
                    throw e;

                } catch (Exception e) {
                    if (!mInstrumentation.onException(r.activity, e)) {
                        throw new RuntimeException(
                                "Unable to pause activity "
                                + r.intent.getComponent().toShortString()
                                + ": " + e.toString(), e);
                    }
                }
                r.paused = true;
            }
        } else {
            // If there was an error, for any reason, tell the activity
            // manager to stop us.
            try {
                ActivityManagerNative.getDefault()
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null, false);
            } catch (RemoteException ex) {
                // Ignore
            }
        }
    }
在performLaunchActivity方法中,Activity的onCreate方法其实调用了Instrumentation的 callActivityOnCreate方法,在该方法中调用了Activity的performCreate方法。
performCreate代码如下:
    final void performCreate(Bundle icicle, PersistableBundle persistentState) {
        onCreate(icicle, persistentState);
        mActivityTransitionState.readState(icicle);
        performCreateCommon();
    }
从中可以很清楚看到调用了onCreate方法。新的Activity启动必须是要等到在旧Activity调用onPause之后才能进行,因此在onPause方法中最好只做一些轻量级的数据保存工作,不然会影响新Activity的显示。为了验证该过程,可以自己动手写写demo测试下!




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值