从源码分析Activity启动时的生命周期

写在前面的话

最近高产似母猪,每天都会写点关于这个系列的总结。周一了,又开始忙碌的一天。项目赶赶赶,bug改改改,盼望着盼望着,终于下班了。突然想起小时候学过的一篇课文《和时间赛跑》,越来越觉得“光阴似箭,日月如梭”了。还以为是那个刚刚来到魔都的毛头小子,突然间发现,现在已然变成了“猥琐大叔”了。
虽然我并不猥琐,虽然我并不是大叔。噢!又想起大学宿舍的猥琐小哥了,那猥琐的样子.....
哎~不扯了,再扯就不用写了。


1. 关于Activity的生命周期

自从开始入Android的坑的时候,就一直念叨着Activity启动时先onCreate,再onStart,最后onResume。各个阶段是啥含义具体不讲了(我不会说我也不知道)。



但是,自从开始做Android就想过,这几个方法究竟是什么时候调用的?又是谁去调用的他?以前呢,自己太菜了(虽然现在也是。。),根本没有好好去看,最近有时间好好总结下关于这方面的知识。



在前面的Android的luncher启动过程中已经讲到,Activity启动的时候会调用ApplicationThread的scheduleLaunchActivity方法。下面从这个地方开始分析整个过程。

2. scheduleLaunchActivity方法

这个方法其实不想说的,这里面只做了一个操作,就是通过Handler发送LAUNCH_ACTIVITY消息。

@Override
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
        ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
        CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
        int procState, Bundle state, PersistableBundle persistentState,
        List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
        boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
    //对变量各种赋值
    ......
    //发送LAUNCH_ACTIVITY消息,并把数据传入
    sendMessage(H.LAUNCH_ACTIVITY, r);
}

这里简单看下这个H是何方神圣private class H extends Handler,好了看完了。这就够了,这就是个Handler。


3. Handler处理LAUNCH_ACTIVITY消息

这里面处理也是很简单的,调用了handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");方法。

public void handleMessage(Message msg) {
    if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
    switch (msg.what) {
        case LAUNCH_ACTIVITY: {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
            final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

            r.packageInfo = getPackageInfoNoCheck(
                    r.activityInfo.applicationInfo, r.compatInfo);
            //调用ActivityThread的handleLaunchActivity方法。
            handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        } break;
    }
    ......
}

4. handleLaunchActivity方法和performLaunchActivity方法

handleLaunchActivity又调用了performLaunchActivity方法去创建,并启动Activity。

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
    ......
    // Initialize before creating the activity
    WindowManagerGlobal.initialize();

    Activity a = performLaunchActivity(r, customIntent);

    if (a != null) {
        r.createdConfig = new Configuration(mConfiguration);
        reportSizeConfigurations(r);
        Bundle oldState = r.state;
                //这里调用Activity的onResume方法
        handleResumeActivity(r.token, false, r.isForward,
                !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
        ......
    } else {
        //Activity为null,则代表启动出现问题,需要关闭
        try {
            ActivityManagerNative.getDefault()
                .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                        Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }
}
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");

    ActivityInfo aInfo = r.activityInfo;
    //对各种信息的非空判断以及为空的时候赋值
    ......

    Activity activity = null;
    try {
        java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
        //通过Instrumentation创建新的Activity
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
        StrictMode.incrementExpectedActivityCount(activity.getClass());
        r.intent.setExtrasClassLoader(cl);
        r.intent.prepareToEnterProcess();
        if (r.state != null) {
            r.state.setClassLoader(cl);
        }
    } catch (Exception e) {
        ......
    }

    try {
        //创建Application
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);
        ......
        if (activity != null) {
            //创建Context
            Context appContext = createBaseContextForActivity(r, activity);
            CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
            Configuration config = new Configuration(mCompatConfiguration);
            if (r.overrideConfig != null) {
                config.updateFrom(r.overrideConfig);
            }
            //这个Window是我们显示的窗体
            Window window = null;
            if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
                window = r.mPendingRemoveWindow;
                r.mPendingRemoveWindow = null;
                r.mPendingRemoveWindowManager = null;
            }
            //调用attach方法
            activity.attach(appContext, this, getInstrumentation(), r.token,
                    r.ident, app, r.intent, r.activityInfo, title, r.parent,
                    r.embeddedID, r.lastNonConfigurationInstances, config,
                    r.referrer, r.voiceInteractor, window);

            if (customIntent != null) {
                activity.mIntent = customIntent;
            }
            r.lastNonConfigurationInstances = null;
            activity.mStartedActivity = false;
            int theme = r.activityInfo.getThemeResource();
            if (theme != 0) {
                activity.setTheme(theme);
            }

            activity.mCalled = false;
            //判断是不是持久化的,可以理解为新的现场保存,查了下说是5.0及以上有的一种更加坚固的保存数据方式
            //true会调用onCreate(@Nullable Bundle savedInstanceState,@Nullable PersistableBundle persistentState)
            //false会调用onCreate(@Nullable Bundle savedInstanceState)
            if (r.isPersistable()) {
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
            if (!activity.mCalled) {
                throw new SuperNotCalledException(
                    "Activity " + r.intent.getComponent().toShortString() +
                    " did not call through to super.onCreate()");
            }
            r.activity = activity;
            r.stopped = true;
            //这里会调用onStart方法
            if (!r.activity.mFinished) {
                activity.performStart();
                r.stopped = false;
            }
            //调用onRestoreInstanceState方法,当然这个是在re-initialized状态下,即重新初始化
            if (!r.activity.mFinished) {
                if (r.isPersistable()) {
                    if (r.state != null || r.persistentState != null) {
                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                                r.persistentState);
                    }
                } else if (r.state != null) {
                    mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                }
            }
            //onPostCreate这个会在程序完全运行起来调用,onStart以后。好像很少用
            if (!r.activity.mFinished) {
                activity.mCalled = false;
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnPostCreate(activity, r.state,
                            r.persistentState);
                } else {
                    mInstrumentation.callActivityOnPostCreate(activity, r.state);
                }
                if (!activity.mCalled) {
                    throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString() +
                        " did not call through to super.onPostCreate()");
                }
            }
        }
        r.paused = true;

        mActivities.put(r.token, r);

    } catch (SuperNotCalledException e) {
        throw e;

    } catch (Exception e) {
        ......
    }

    return activity;
}

Instrumentation.java
public Activity newActivity(ClassLoader cl, String className,
        Intent intent)
        throws InstantiationException, IllegalAccessException,
        ClassNotFoundException {
    //通过反射创建Activity
    return (Activity)cl.loadClass(className).newInstance();
}

从上面的分析来看,我们显示使用Instrumentation.newActivity方法,通过反射创建一个Activity对象,接着会调用attach这个隐藏方法。之后根据是否是异常状态恢复,去掉用onCreate方法,接着调用onStart方法,如果是在重新初始化的时候,则会调用callActivityOnRestoreInstanceState方法,最后在程序完全运行起来调调用Activity的callActivityOnPostCreate(这个很少用到啊)。


5. 还是先说下 onResume

在上面的代码中,我们在执行完performLaunchActivity方法会执行handleResumeActivity方法。在这里,我们是执行了Activity的onResume方法。

final void handleResumeActivity(IBinder token,
        boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
    ActivityClientRecord r = mActivities.get(token);
    ......
    //执行onResume方法
    r = performResumeActivity(token, clearHide, reason);
    //onResume是activity与用户能进行交互时被执行,用户可以获得activity的焦点,能够与用户交互
    if (r != null) {
        final Activity a = r.activity;
        final int forwardBit = isForward ?
                WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
        
        boolean willBeVisible = !a.mStartedActivity;
        ......
        //通过ViewManager或者说WindowManager将要显示的Activity显示出来,这里以后应该会分析,不急不急
        if (r.window == null && !a.mFinished && willBeVisible) {
            r.window = r.activity.getWindow();
            View decor = r.window.getDecorView();
            decor.setVisibility(View.INVISIBLE);
            ViewManager wm = a.getWindowManager();
            WindowManager.LayoutParams l = r.window.getAttributes();
            a.mDecor = decor;
            l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
            l.softInputMode |= forwardBit;
            if (r.mPreserveWindow) {
                a.mWindowAdded = true;
                r.mPreserveWindow = false;
                ViewRootImpl impl = decor.getViewRootImpl();
                if (impl != null) {
                    impl.notifyChildRebuilt();
                }
            }
            if (a.mVisibleFromClient && !a.mWindowAdded) {
                a.mWindowAdded = true;
                wm.addView(decor, l);
            }
        } else if (!willBeVisible) {
            if (localLOGV) Slog.v(
                TAG, "Launch " + r + " mStartedActivity set");
            r.hideForNow = true;
        }
        ......
        if (!r.onlyLocalRequest) {
            r.nextIdle = mNewActivities;
            mNewActivities = r;
            Looper.myQueue().addIdleHandler(new Idler());
        }
        r.onlyLocalRequest = false;

        // Tell the activity manager we have resumed.
        if (reallyResume) {
            try {
                //通过AMS设置状态
                ActivityManagerNative.getDefault().activityResumed(token);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }

    } else {
        //和启动一样,如果有问题则结束掉
        try {
            ActivityManagerNative.getDefault()
                .finishActivity(token, Activity.RESULT_CANCELED, null,
                        Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }
}

6. 总结

咦?好像有点不对,如果是启动新的Activity时,会调用上一个页面的onStop方法啊?不对啊,看看怎么编下去吧。



7. 迟到的onStop

其实这个onStop调用时机我在上面的代码也展示出来了,只不过没有标明。就在这段代码中:

Looper.myQueue().addIdleHandler(new Idler());

private class Idler implements MessageQueue.IdleHandler {
    @Override
    public final boolean queueIdle() {
        ActivityClientRecord a = mNewActivities;
        boolean stopProfiling = false;
        if (mBoundApplication != null && mProfiler.profileFd != null
                && mProfiler.autoStopProfiler) {
            stopProfiling = true;
        }
        if (a != null) {
            mNewActivities = null;
            IActivityManager am = ActivityManagerNative.getDefault();
            ActivityClientRecord prev;
            do {
                if (a.activity != null && !a.activity.mFinished) {
                    try {
                        //通过AMS调用activityIdle方法,最终会执行onStop方法
                        am.activityIdle(a.token, a.createdConfig, stopProfiling);
                        a.createdConfig = null;
                    } catch (RemoteException ex) {
                        throw ex.rethrowFromSystemServer();
                    }
                }
                prev = a;
                a = a.nextIdle;
                prev.nextIdle = null;
            } while (a != null);
        }
        ......
        return false;
    }
}
AMS:
@Override
public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
    final long origId = Binder.clearCallingIdentity();
    synchronized (this) {
        ActivityStack stack = ActivityRecord.getStackLocked(token);
        //调用StackSupervisor.activityIdleInternalLocked方法
        if (stack != null) {
            ActivityRecord r =
                    mStackSupervisor.activityIdleInternalLocked(token, false, config);
            if (stopProfiling) {
                if ((mProfileProc == r.app) && (mProfileFd != null)) {
                    try {
                        mProfileFd.close();
                    } catch (IOException e) {
                    }
                    clearProfilerLocked();
                }
            }
        }
    }
    Binder.restoreCallingIdentity(origId);
}
ActivityStackSupervisor.java
final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
        Configuration config) {
    ......

    for (int i = 0; i < NS; i++) {
        r = stops.get(i);
        final ActivityStack stack = r.task.stack;
        if (stack != null) {
            if (r.finishing) {
                stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
            } else {
                //这里去真正stop Activity
                stack.stopActivityLocked(r);
            }
        }
    }
    ......

    return r;
}
ActivityStack.java
final void stopActivityLocked(ActivityRecord r) {
    if (r.app != null && r.app.thread != null) {
        adjustFocusedActivityLocked(r, "stopActivity");
        r.resumeKeyDispatchingLocked();
        try {
            ......
            //调用ApplicationThread的scheduleStopActivity方法,真正stop activity
            r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags);
            ......
        } catch (Exception e) {
            
        }
    }
}

上面一大部分就是关于onStop的大体过程,先是将Activity resume后将Idler(这个意思懒汉,无所事事的人)放到消息队列中,当消息进行执行是,会执行其中的方法,并通过AMS调用activityIdle方法,AMS又调用ActivityStackSupervisor的activityIdleInternalLocked方法,而activityIdleInternalLocked方法又会调用ActivityStack的stopActivityLocked方法,又跑到ApplicationThread中的scheduleStopActivity方法去真正stop activity。下面简单看下这个方法执行过程。


8. onStop真正执行过程

这里就简单看下,无非还是通过Handler发送消息,在消息执行是调用ActivityThread的方法去执行stop。下面看下源码:

public final void scheduleStopActivity(IBinder token, boolean showWindow,
        int configChanges) {
    int seq = getLifecycleSeq();
    if (DEBUG_ORDER) Slog.d(TAG, "stopActivity " + ActivityThread.this
            + " operation received seq: " + seq);
    sendMessage(
        showWindow ? H.STOP_ACTIVITY_SHOW : H.STOP_ACTIVITY_HIDE,
        token, 0, configChanges, seq);
}

private void handleStopActivity(IBinder token, boolean show, int configChanges, int seq) {
    ......
    //真正执行stop
    performStopActivityInner(r, info, show, true, "handleStopActivity");
    ......
}
private void performStopActivityInner(ActivityClientRecord r,
        StopInfo info, boolean keepShown, boolean saveState, String reason) {
        ......
        //如果有必要先执行pause方法
        performPauseActivityIfNeeded(r, reason);
        ......
        // Next have the activity save its current state and managed dialogs...
        if (!r.activity.mFinished && saveState) {
            if (r.state == null) {
                callCallActivityOnSaveInstanceState(r);
            }
        }

        if (!keepShown) {
            try {
                // 执行onStop方法
                r.activity.performStop(false /*preserveWindow*/);
            } catch (Exception e) {
                if (!mInstrumentation.onException(r.activity, e)) {
                    throw new RuntimeException(
                            "Unable to stop activity "
                            + r.intent.getComponent().toShortString()
                            + ": " + e.toString(), e);
                }
            }
            r.stopped = true;
        }
    }
}

整个流程大概就这样,Activity的生命周期基本执行完成了。


9. 我还有话说

关于Instrumentation的各种方法,举个例子来说,例如Instrumentation.callActivityOnCreate(activity, r.state)方法,这里会执行

public void callActivityOnCreate(Activity activity, Bundle icicle) {
        //创建前
        prePerformCreate(activity);
        //执行onCreate方法
        activity.performCreate(icicle);
        //创建完成
        postPerformCreate(activity);
}
Activity.java
final void performCreate(Bundle icicle) {
    restoreHasCurrentPermissionRequest(icicle);
    //真正执行onCreate
    onCreate(icicle);
    mActivityTransitionState.readState(icicle);
    performCreateCommon();
}

这个Instrumentation可以说是个小秘书,我可以替大老板执行任务,并且在执行任务前后悄悄的做点事情,这感觉就是代理模式啊!!


写在后面的话

有完没完了啊。好吧,真的结束了。后面还是会有分析,整理整理思路,赶明再出发。


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容