Android Activity原理分析 联系客服

发布时间 : 星期日 文章Android Activity原理分析更新完毕开始阅读

5.1.6 OnResume的调用

回到图5.1.4,我们可以看到从performLaunchActivity返回后,还需要经历这个逻辑,

handleLaunchActivity(r, null)这边是显示流程 if (a != null)r.createdConfig = new Configuration(mConfiguration)handleResumeActivity(r.token, false, r.isForward)这里很关键,触发了整个显示的过程关键的函数就是handleResumeActivity,它一方面触发了真正的显示过程,一方面实现了onResume的调用逻辑;

正如我们前面分析过的,onResume的执行包括两种场景,一种是从onCreate——>onStart—

—>onResume,还有一种是onRestart——>onStart——>onResume,后一种路径是从暂停到停止再继续的过程,这个逻辑我们留到下一节细讲,这里考虑的是我们正在讨论的场景,也就是第一次启动一个activity,所以是第一种流程;

handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) ActivityThread.java更加详细的逻辑请看activity_startcallActivityOnResume(Activity activity) ActivityRecord r = performResumeActivity(token, clearHide)ActivityThread.javaactivity.onResumer.activity.performResume调用onResume这个函数通常会被重载performResumeResume的路径Activity.javamInstrumentation.callActivityOnResume(this)mCalled = true我去掉了第二种流程相关的逻辑,这里关键的是performResume,它真正调用我们提供的onResume函数,同时它还有可能会调用onRestart和onStart;

?Tech, 2010-2-5

Page 21 of 38

这个图基本上没有什么其它逻辑,只是从ActivityThread类到了activity类,而已;

5.2

从暂停到继续的过程分析 5.2.1

暂停操作的原由

复杂的都是第一次启动的逻辑,有了上面的分析,再看下面,就会发现很多代码都是我们看到过的,只是当时走的分支不一样而已;

我们这次分析的场景是一个旧的activity A被新的activity B起来并完全覆盖,然后再被resume的过程,当然我们的主角还是A,因为它才会经历暂停到继续的过程;

当要显示一个Activity的时候,会调用resumeTopActivityLocked(HistoryRecord prev)函数,前面我们也就见识过它了,它每次的原理就是需要从一个列表里面挑选出不等于prev的最上层的HistoryRecord,通常这个prev或者是NULL或者是上一个显示的HistoryRecord,当挑选出适当的activity的时候,进行一些简单的判断就到了下面的代码: if (mResumedActivity != null) {

if (DEBUG_SWITCH) Log.v(TAG, \ startPausingLocked(userLeaving, false); return true; }

先判断mResumedActivity是否为null,它是在上面地方设置的呢?

如果你记忆足够好,就会记得,前面当新的activityThread起来以后会触发调用函数realStartActivityLocked,这是在attach的过程中触发的,可以回头看看5.1.3;

我们只分析了它调用app.thread.scheduleLaunchActivity的逻辑,之后的我们就没看了,现在是时候了:

if (andResume) {

// As part of the process of launching, ActivityThread also performs // a resume.

r.state = ActivityState.RESUMED; r.icicle = null;

r.haveState = false; r.stopped = false;

mResumedActivity = r; r.task.touchActiveTime(); completeResumeLocked(r);

pauseIfSleepingLocked(); }

这个andResume是为true的,进来以后,把这个mResumedActivity赋值为了r,也就是我们刚启动过的这个HistoryRecord;

好,现在我们知道了这个mResumedActivity是不为空的,那么就可以开始调用

startPausingLocked(userLeaving, false)了,也许你会觉得奇怪,进入这个函数的目的是为了显示一个新的activity,怎么会调用startPausingLocked函数以后就返回true了呢?这个问题,后面会有答案;我们现在还是先看看这个函数startPausingLocked吧;

?Tech, 2010-2-5 Page 22 of 38

startPausingLocked(boolean userLeaving, boolean uiSleeping)HistoryRecord prev = mResumedActivitymResumedActivity = null; mPausingActivity = prev; mLastPausedActivity = prev; prev.state = ActivityState.PAUSING if (prev.app != null && prev.app.thread != null)prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,prev.configChangeFlags这里先把当前在最上面的HistoryRecorcd mResumeActivity赋值给了prev,然后把mResumeActivity设置为null了,再把mPausingActivity 赋值为prev,表示它是当前正在暂停的记录,再把这个记录的状态设置为ActivityState.PAUSING;最后通过prev.app.thread.schedulePauseActivity开始开启暂停的流程;通常这个带thread的,都是指ActivityThread,这样的调用方法都会经历Binder到另外一个进程;

schedulePauseActivity(IBinder token, boolean finished,Binder触发 boolean userLeaving, int configChanges)prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,prev.configChangeFlags queueOrSendMessage( finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY, token,(userLeaving ? 1 : 0),configChanges)还记得我前面说的吗?带schedule的通常都是不真正干事的,这里也就是queue一个消息到消息队列里面,等待被分发,这里的消息类型分为PAUSE_ACTIVITY_FINISHING和

PAUSE_ACTIVITY,它们的区别在于,前面那个表示正在finish,而finish的意思就是说需要destory,对于应用开发者来说,简单一点就是会触发onDestory的调用,不过,通常开发者也不会重载这个函数;

在主循环里面会把属于这个线程的消息队列取出来,一个一个的调用其消息的回调线程或者其handleMessage,详见附录【1】;

?Tech, 2010-2-5 Page 23 of 38

handleMessage(Message msg)case PAUSE_ACTIVITYcase PAUSE_ACTIVITY_FINISHINGhandlePauseActivity((IBinder)msg.obj, true, msg.arg1 != 0, msg.arg2)handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2)可以看到对于这个两个消息都是调用相同的函数,只不过是第二个参数不一样,下面看看这个函数handlePauseActivity:

handlePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges) ActivityRecord r = mActivities.get(token)if (r != null) if (userLeaving)r.activity.mConfigChangeFlags |= configChangesBundle state = performPauseActivity(token, finished, true)ActivityManagerNative.getDefault().activityPaused(token, state)performUserLeavingActivity这个函数的作用就是告诉activity用户要离开了,如果设置了回调函数,相应的回调函数会被触发前面在创建activity的时候我说过会把Binder和activity关联起来,这里就是根据这个token Binder取出相应的activity记录,先判断userLeaving是否为true,如果为真,就通知应用,这样的话应用就可以再用户(即将)离开的时候做一些特别的事情; 设置配置是否改变的标志;

再调用performPauseActivity进行真正的pause操作; 最后通知activityManagerService暂停动作也就完成;

最后这两步都非常的重要,前一步是完成暂停操作,后一步是进入到stop,并触发新的activity的显示,我们一个个来看;

5.2.2

onPause的调用

很快就可以看到我们熟悉的onPause操作了;

?Tech, 2010-2-5 Page 24 of 38