Activity关闭源码分析(三)
来源:互联网 发布:caffe视频教程百度云 编辑:程序博客网 时间:2024/05/29 15:51
对于Activity的启动可以观看上一篇android启动流程分析(二)进行查看下面分析activity的关闭流程如下图:
看高清图请下载
关闭activity的时候回调用finish方法代码如下:
public void finish() { finish(DONT_FINISH_TASK_WITH_ACTIVITY); }
private void finish(int finishTask) { if (mParent == null) {// int resultCode; Intent resultData; synchronized (this) { resultCode = mResultCode; resultData = mResultData; } if (false) Log.v(TAG, "Finishing self: token=" + mToken); try { if (resultData != null) { resultData.prepareToLeaveProcess(this); } if (ActivityManagerNative.getDefault() .finishActivity(mToken, resultCode, resultData, finishTask)) {//调用ActivityManagerService mFinished = true; } } catch (RemoteException e) { // Empty } } else { mParent.finishFromChild(this); } }在这里稍微解释下mParent这个参数:Activity中存在父子Activity的关系。mParent参数是对那些在ActivityGroup中的Activity来说的。比如说在TabActivity中的Tab页面里嵌套的Activity,他们的mParent就是TabActivity。mParent的赋值在Activity.setParent(Activity parent)方法中定义。大多数Activity.mParent为空,因此此处直接往AMS.finishActivity流程走。这里我们只分析没有父类的,以及上父类的关闭原理也差不多。
对于ActivityManagerNative.getDefault().finishActivity(mToken, resultCode, resultData, finishTask)这句话实际就是调用了Ams里面的finishActivity方法(为什么可以查看前面的文章android启动流程分析(一)),直接查看Ams中的方法代码如下:
public final boolean finishActivity(IBinder token, int resultCode, Intent resultData, int finishTask) { ...... try { boolean res; final boolean finishWithRootActivity = finishTask == Activity.FINISH_TASK_WITH_ROOT_ACTIVITY; if (finishTask == Activity.FINISH_TASK_WITH_ACTIVITY || (finishWithRootActivity && r == rootR)) { // If requested, remove the task that is associated to this activity only if it // was the root activity in the task. The result code and data is ignored // because we don't support returning them across task boundaries. Also, to // keep backwards compatibility we remove the task from recents when finishing // task with root activity. res = removeTaskByIdLocked(tr.taskId, false, finishWithRootActivity); if (!res) { Slog.i(TAG, "Removing task failed to finish activity"); } } else { res = tr.stack.requestFinishActivityLocked(token, resultCode, resultData, "app-request", true);//关闭activity if (!res) { Slog.i(TAG, "Failed to finish by app-request"); } } return res; } finally { Binder.restoreCallingIdentity(origId); } } }从上面的代码可以看出这个关闭activity的语句调用的是ActivityStack类里面的requestFinishActivityLocked方法,代码如下:
final boolean requestFinishActivityLocked(IBinder token, int resultCode, Intent resultData, String reason, boolean oomAdj) { ...... finishActivityLocked(r, resultCode, resultData, reason, oomAdj); return true; }
final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData, String reason, boolean oomAdj) { ...... if (mResumedActivity == r) {//当前activity关闭的时候调用 ...... if (mPausingActivity == null) { if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish needs to pause: " + r); if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING, "finish() => pause with userLeaving=false"); startPausingLocked(false, false, false, false); } if (endTask) { mStackSupervisor.removeLockedTaskLocked(task); } } else if (r.state != ActivityState.PAUSING) {//不在暂停状态的情况下调用 ...... return finishCurrentActivityLocked(r, (r.visible || r.nowVisible) ? FINISH_AFTER_VISIBLE : FINISH_AFTER_PAUSE, oomAdj) == null; } else { if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish waiting for pause of: " + r); } return false; }如上面的代码有两个分支,我们是调用的activity的finish因此我们走的是第一种,调用了startPausingLocked方法代码如下:
final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming, boolean dontWait) { ..... prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing, userLeaving, prev.configChangeFlags, dontWait); } catch (Exception e) { // Ignore exception, if process died other code will cleanup. Slog.w(TAG, "Exception thrown during pause", e); mPausingActivity = null; mLastPausedActivity = null; mLastNoHistoryActivity = null; } } else { mPausingActivity = null; mLastPausedActivity = null; mLastNoHistoryActivity = null; } ......... }对于上面的prev.app.thread代表的是ActivityThread::ApplicationThread不明可以查看前面的文章(android启动流程分析(一))schedulePauseActivity方法代码如下:
public final void schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges, boolean dontReport) { int seq = getLifecycleSeq(); if (DEBUG_ORDER) Slog.d(TAG, "pauseActivity " + ActivityThread.this + " operation received seq: " + seq); sendMessage( finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY, token, (userLeaving ? USER_LEAVING : 0) | (dontReport ? DONT_REPORT : 0), configChanges, seq); }虽然上面的Message有两种状态但是最终调用的都是同一个方法代码如下:
private void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges, boolean dontReport, int seq) { ...... performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity"); ..... if (!dontReport) { try { ActivityManagerNative.getDefault().activityPaused(token); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } mSomeActivitiesChanged = true; } }
final Bundle performPauseActivity(ActivityClientRecord r, boolean finished, boolean saveState, String reason) {...... // Next have the activity save its current state and managed dialogs... if (!r.activity.mFinished && saveState) { callCallActivityOnSaveInstanceState(r);//调用activity的OnSaveInstanceState方法 } performPauseActivityIfNeeded(r, reason);//调用activity的onpause方法 ...... }
根据上面的代码可知activity在没有调用关闭以及saveState为true(有AMS控制的)时候会调用OnSaveInstanceState方法,接下来调用onPause方法,进一步分析performPauseActivityIfNeeded代码如下:
private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) { ...... mInstrumentation.callActivityOnPause(r.activity); ...... r.paused = true; }
调用了Activity类中的下面方法,上面调用的是Instrumentation类中的方法
final void performPause() { mDoReportFullyDrawn = false; mFragments.dispatchPause(); mCalled = false; onPause(); mResumed = false; if (!mCalled && getApplicationInfo().targetSdkVersion >= android.os.Build.VERSION_CODES.GINGERBREAD) { throw new SuperNotCalledException( "Activity " + mComponent.toShortString() + " did not call through to super.onPause()"); } mResumed = false; }到这里位置onPause方法就被调用了,接下来在ActivityThread这个类中的handlePauseActivity方法中来由一句话调用了代码如下:
// Tell the activity manager we have paused.通过这意思是activity进入paused状态的时候调用 if (!dontReport) { try { ActivityManagerNative.getDefault().activityPaused(token); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } }对于ActivityManagerNative.getDefault().activityPaused(token);这句话一看就知道最终调用的是AMS中的activityPaused方法,此方法代码如下:
@Override public final void activityPaused(IBinder token) { final long origId = Binder.clearCallingIdentity(); synchronized(this) { ActivityStack stack = ActivityRecord.getStackLocked(token); if (stack != null) { stack.activityPausedLocked(token, false); } } Binder.restoreCallingIdentity(origId); }
接下来调用了ActivityStack类中的activityPausedLocked方法,代码如下
private void completePauseLocked(boolean resumeNext) { ActivityRecord prev = mPausingActivity; if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Complete pause: " + prev); if (prev != null) { final boolean wasStopping = prev.state == ActivityState.STOPPING; prev.state = ActivityState.PAUSED; if (prev.finishing) {//这个一般不不会调用之后再内存不足的时候才会调用 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Executing finish of activity: " + prev); prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false); } else if (prev.app != null) { if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueue pending stop if needed: " + prev + " wasStopping=" + wasStopping + " visible=" + prev.visible); if (mStackSupervisor.mWaitingVisibleActivities.remove(prev)) { if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Complete pause, no longer waiting: " + prev); } if (prev.deferRelaunchUntilPaused) { // Complete the deferred relaunch that was waiting for pause to complete. if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Re-launching after pause: " + prev); relaunchActivityLocked(prev, prev.configChangeFlags, false, prev.preserveWindowOnDeferredRelaunch); } else if (wasStopping) { // We are also stopping, the stop request must have gone soon after the pause. // We can't clobber it, because the stop confirmation will not be handled. // We don't need to schedule another stop, we only need to let it happen. prev.state = ActivityState.STOPPING; } else if ((!prev.visible && !hasVisibleBehindActivity()) || mService.isSleepingOrShuttingDownLocked()) { // If we were visible then resumeTopActivities will release resources before // stopping. addToStopping(prev, true /* immediate */); } } else { if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "App died during pause, not stopping: " + prev); prev = null; } // It is possible the activity was freezing the screen before it was paused. // In that case go ahead and remove the freeze this activity has on the screen // since it is no longer visible. prev.stopFreezingScreenLocked(true /*force*/); mPausingActivity = null; } if (resumeNext) { ...... mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);//回复前面的activy...... }...... }
在这里调用resumeFocusedStackTopActivityLocked方法进行启动上一个Activity代码如下:
boolean resumeFocusedStackTopActivityLocked( ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) { if (targetStack != null && isFocusedStack(targetStack)) { return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions); } final ActivityRecord r = mFocusedStack.topRunningActivityLocked(); if (r == null || r.state != RESUMED) { mFocusedStack.resumeTopActivityUncheckedLocked(null, null); }
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) { if (mStackSupervisor.inResumeTopActivity) { // Don't even start recursing. return false; } boolean result = false; try { // Protect against recursion. mStackSupervisor.inResumeTopActivity = true; if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) { mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN; mService.updateSleepIfNeededLocked(); } result = resumeTopActivityInnerLocked(prev, options); } finally { mStackSupervisor.inResumeTopActivity = false; } return result; }
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {...... Bundle resumeAnimOptions = null; if (anim) { ActivityOptions opts = next.getOptionsForTargetActivityLocked(); if (opts != null) { resumeAnimOptions = opts.toBundle(); } next.applyOptionsLocked(); } else { next.clearOptionsLocked(); } ActivityStack lastStack = mStackSupervisor.getLastStack(); if (next.app != null && next.app.thread != null) { ...... try { // Deliver all pending results. ArrayList<ResultInfo> a = next.results; if (a != null) { final int N = a.size(); if (!next.finishing && N > 0) { if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "Delivering results to " + next + ": " + a); next.app.thread.scheduleSendResult(next.appToken, a); } } if (next.newIntents != null) { next.app.thread.scheduleNewIntent(next.newIntents, next.appToken); } ...... next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState, mService.isNextTransitionForward(), resumeAnimOptions); mStackSupervisor.checkReadyForSleepLocked(); ..... }
对于上面next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState, mService.isNextTransitionForward(), resumeAnimOptions);方法就是activity启动的时候调用的一样的可以参照上一篇文章(android启动流程分析(二)),这里面会调用onReStart-->onStart--->onResume生命周期我们在看看handleResumeActivity方法
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {...... // TODO Push resumeArgs into the activity for consideration r = performResumeActivity(token, clearHide, reason); ...... if (!r.onlyLocalRequest) { r.nextIdle = mNewActivities; mNewActivities = r; if (localLOGV) Slog.v( TAG, "Scheduling idle handler for " + r); Looper.myQueue().addIdleHandler(new Idler()); } ..... }通过上面的方法我们能看到在运行完performResumeActivity方法之后会执行Looper.myQueue().addIdleHandler(new Idler());可以查看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 (localLOGV) Slog.v( TAG, "Reporting idle of " + a + " finished=" + (a.activity != null && a.activity.mFinished)); if (a.activity != null && !a.activity.mFinished) { try { 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); } if (stopProfiling) { mProfiler.stopProfiling(); } ensureJitEnabled(); return false; } }
内部有一个queueIdle的回调方法,当它被添加到MessageQueue之后就会回调该方法,我们可以发现在这个方法体中调用了ActivityManagerNative.getDefault.activityIdle方法,通过之前的我们知道ActivityManagerNative.getDefault方法最终调用的是AMs中的方法activityIdle查看代码如下:
@Override public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) { ..... ActivityRecord r = mStackSupervisor.activityIdleInternalLocked(token, false, config);// ..... }
接下来调用下面方法ActivityStackSupervisor这个类中的方法
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 { stack.stopActivityLocked(r); } } }...... }
通过判断语句可以知道如果要关闭就走第一条,否则就是进行stop状态,查看一下finishCurrentActivityLocked方法如下(在ActivityStack中):
final ActivityRecord finishCurrentActivityLocked(ActivityRecord r, int mode, boolean oomAdj) { ...... boolean activityRemoved = destroyActivityLocked(r, true, "finish-imm");...... }
final boolean destroyActivityLocked(ActivityRecord r, boolean removeFromApp, String reason) { ...... try { if (DEBUG_SWITCH) Slog.i(TAG_SWITCH, "Destroying: " + r); r.app.thread.scheduleDestroyActivity(r.appToken, r.finishing, r.configChangeFlags); } catch (Exception e) { // We can just ignore exceptions here... if the process // has crashed, our death notification will clean things // up. //Slog.w(TAG, "Exception thrown during finish", e); if (r.finishing) { removeActivityFromHistoryLocked( r, topTask, reason + " exceptionInScheduleDestroy"); removedFromHistory = true; skipDestroy = true; } } ...... }通过前面的分析r.app.thread.scheduleDestroyActivity(r.appToken, r.finishing,r.configChangeFlags);这就话实际上是调用了ActivityThread::ApplicationThread中的方法
private void handleDestroyActivity(IBinder token, boolean finishing, int configChanges, boolean getNonConfigInstance) { ActivityClientRecord r = performDestroyActivity(token, finishing, configChanges, getNonConfigInstance); ...... if (finishing) { try { ActivityManagerNative.getDefault().activityDestroyed(token); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } mSomeActivitiesChanged = true; }
private ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing, int configChanges, boolean getNonConfigInstance) { ...... r.activity.performStop(r.mPreserveWindow); r.activity.mCalled = false; mInstrumentation.callActivityOnDestroy(r.activity);...... }上面的方法在进一步分析就能知道剩下的声明周期是onStop--->onDestory
总结:通过上一篇和这这一篇得出activity的启动和关闭流程的生命周期的如下:
1、当启动第一个Activity_A的时候的生命周期运行的方法:
onCreate--->onStart--->onPostCreate--->onResume--->onPostResume
这是锁屏运行方法
onPause--->onSaveInstanceState--->onStop
开屏运行方法
onRestart--->onStart--->onResume--->onPostResume
2、在Activity_A中打开Activity_B的生命周期运行的方法:
A_onPause--->B_onCreate--->B_onStart--->B_onPostCreate--->B_onResume--->B_onPostResume--->A_onSaveInstanceState---->A_onStop
3、关闭Activity_B
B_onPause--->A_onRestart--->A_onStart--->A_onResume--->A_onPostResume--->B_onStop---->B_onDestroy
- Activity关闭源码分析(三)
- Activity启动流程源码分析之startActivity启动(三)
- Activity的三种关闭方法分析(finish;onDestory;exit)
- Adnroid Activity源码分析
- Activity.setContentView()源码分析
- Activity TouchEvent 源码分析
- Activity启动源码分析
- Activity源码分析
- Activity.startActivity源码分析
- Activity启动源码分析
- JUnit源码分析(三)
- Log4net源码分析(三)
- Log4net源码分析(三)
- Logcat源码分析(三)
- Log4net源码分析(三)
- pomelo源码分析(三)
- H264源码分析(三)
- mosquitto源码分析(三)
- CDH参考文档
- 安卓开发实现点击验证码变灰并倒计时
- python笔记005——os.path模块用法详解
- Lintcode82 Single Number solution题解
- 搭建LNMP环境(CentOS 6)
- Activity关闭源码分析(三)
- spring mvc实现简单上传文件
- 【iOS开发】如何将 iOS 项目的编译速度提高5倍
- eclipse的web工程转换
- Android RecyclerView 的基本使用
- Mysql命令大全
- UITableViewCell上的删除按钮(tableView自带的和自定义的)
- Python 并行分布式框架之 Celery
- MongoDB Windows环境安装及配置