Android Activity原理分析 联系客服

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

performPauseActivity(IBinder token, boolean finished, boolean saveState)ActivityRecord r = mActivities.get(token)return r != null ? performPauseActivity(r, finished, saveState) : nullperformPauseActivity(ActivityRecord r, boolean finished, boolean saveState)if (r.paused)if (finished) if (!r.activity.mFinished && saveState)mInstrumentation.callActivityOnPause(r.activity)r.paused = trueif (r.activity.mFinished)r.activity.mFinished = true;state = new BundlemInstrumentation.callActivityOnSaveInstanceState(r.activity, state)callActivityOnPause(Activity activity)return nullactivity.performPauseperformPauseonPause这个一般会被重载mCalled = true先取出相应的ActivityRecord(注意现在的执行逻辑在ActivityThread的线程);

如果不为空,就调用performPauseActivity;前面我说过带schedule的通常都只是安排负责放消息,而真正处理消息的都是带handle的,比如对于schedule函数scheduleXXX,最后的消息处理函数就是handleXXX,基本上都是整个原则,而handle通常也是一个大的函数,真正负责实施的都是些名字里面带有perform的函数,比如performXXX;

?Tech, 2010-2-5

Page 25 of 38

这里的performPauseActivity有两个参数不一样,进入到带ActivityRecord的performPauseActivity以后,先判断整个记录是否已经被销毁了,那么就直接返回;

如果finish为true,也就是说这个activity正准备销毁,那么设置标志;

如果它没准备销毁,那么就会通知这个activity做一些保存特别是UI上的(比如dialog)保存信息,当回来的时候才能恢复,注意这个函数和onPause,onStop有一些地方相识,都是在特定的时候做一些保存,但是Android的解释说它们的区别在于,onPause的调用逻辑在于只要是从前台到后台都会执行,比如一个新的activity弹出后,并没有完全覆盖掉旧的,并且旧的activity不会被杀掉,那么这个旧的activity的onSaveInstanceState函数等就不会被执行,而且如果从activity B浏览回activity A的时候,B上的onSaveInstanceState也不会被执行,因为它的状态不需要被恢复,总之当一个activity的状态需要恢复的时候,那么可能就会触发这个函数的执行,而onPause,onStop函数是不管什么样的情形都会按照严格的时序执行的;

好,倒数第二个路径,就是我们要找到的onPause的执行路径了,在这里我们需要做一些保存的工作,比如camra的onPause就做了很多特效信息的保存,camera的关闭,UI上的一些复位等等,总之该做的释放都做了;

最后设置标志位r.paused=true,表示也就被暂停了;

5.2.3

onStop的调用

在前面讨论过的函数handlePauseActivity里面通过performPauseActivity函数执行真正的pause操作,然后再通过ActivityManagerNative.getDefault().activityPaused(token, state)通知ActivityManagerService,我们看看这个逻辑都干了啥事?

我就略去了中间的Binder过程,直接进入到了另外的进程ActivityManagerService,如下:

activityPaused(IBinder token, Bundle icicle)activityPaused(token, icicle, false)这是两个同名函数,参数不一样;

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

activityPaused(IBinder token, Bundle icicle, boolean timeout)index = indexOfTokenLocked(token)if (index >= 0) r = (HistoryRecord)mHistory.get(index)if (mPausingActivity == r)r.state = ActivityState.PAUSEDcompletePauseLocked这个函数是一个通知函数,先判断正在暂停的那个记录和这个已经暂停的记录是否一致,如果一致就调用completePauseLocked完成整个暂停过程;

completePauseLocked if (prev != null)if (!mSleeping && !mShuttingDown)if (prev.finishing)else if (prev.app != null)elsemPausingActivity = nullresumeTopActivityLocked(prev)prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE) if (prev.configDestroy)mStoppingActivities.add(prev)destroyActivityLocked(prev, true)if (mStoppingActivities.size() > 3)msg.what = ActivityManagerService.IDLE_NOW_MSG;mHandler.sendMessage(msg)

?Tech, 2010-2-5

Page 27 of 38

先判断这个暂停的记录是否为空;

如果不为空,则判断是否需要finish,如果需要就结束掉它;

否则判断这个记录是否有配置过Destory,如果有同样也是destory掉它;

否则就把这个记录加入到将要结束的活动列表中,留到后面去处理,再判断这个列表大小是否大

于3,如果是,那么就发送一个消息,开启停止操作的流程;

再设置mPuasingActivity为null;

最右边的那一路,回答了我们先前的问题,别忘了,我们走到这里的原因是,因为我们本来是想

显示一个新的activity,没想到,需要先暂停当前的这个activity,所以走到这里了,现在这条路径就是重新回去显示的,它的逻辑我就不分析了,前面已经分析过了;

我们还是看看这个停止消息的发送了, Message msg = Message.obtain();

msg.what = ActivityManagerService.IDLE_NOW_MSG; mHandler.sendMessage(msg) 可以看到就是发送了一个消息,叫做IDLE_NOW_MSG,接下来,按照惯例,需要到handleMessage

那里去找了;

handleMessage(Message msg)这里是onStop的调用逻辑case IDLE_TIMEOUT_MSGcase IDLE_NOW_MSGactivityIdleInternal(token, true, null)activityIdle(token, null)activityIdle(IBinder token, Configuration config)调用activityIdleInternal(token, false, config)在这个消息处理函数里面对这两个消息都会最终调用activityIdleInternal来触发stop流程; 它们的区别也只在调用activityIdleInternal的第二个参数,对于TIMEOUT的消息第二个参数为true,

否则为假;

这个函数做的事情比较多,因为它的名字表示它是在activity Idle的时候才会被触发调用的;

但我们只关心两点,一个是Stoping Activity record的处理,一个是Finishing Activity Record的处理,

相关代码如下:

for (i=0; i

HistoryRecord r = (HistoryRecord)stops.get(i); synchronized (this) { if (r.finishing) {

?Tech, 2010-2-5

Page 28 of 38