finish()和onDestroy() 区别什么?

1.finish 做了什么?

finsh 是我们主动调用的。起点源于

  • android.app.Activity#finish()

主要是把当前Activity从Task栈中移除。

1
2
3
4
public void finish() {
//关闭Activity,但是不关闭task栈
finish(DONT_FINISH_TASK_WITH_ACTIVITY);
}
  • android.app.Activity#finish(int)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
private void finish(int finishTask) {
if (mParent == null) {
int resultCode;
Intent resultData;
synchronized (this) {
resultCode = mResultCode;
resultData = mResultData;
}
try {
if (resultData != null) {
// 有数据需要返回给调用方,比如startActivityForResult
resultData.prepareToLeaveProcess(this);
}

//这里实际实际上是通过android.app.IActivityManager$Stub$Proxy, 也就AIDL Binder 机制
//把mToken发送到AMS
if (ActivityManager.getService()
.finishActivity(mToken, resultCode, resultData, finishTask)) {
mFinished = true;
}
} catch (RemoteException e) {
// Empty
}
} else {
mParent.finishFromChild(this);
}
---
}
  • com.android.server.am.ActivityManagerService#finishActivity
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/**
* This is the internal entry point for handling Activity.finish().
*
* @param token The Binder token referencing the Activity we want to finish.
* @param resultCode Result code, if any, from this Activity.
* @param resultData Result data (Intent), if any, from this Activity.
* @param finishTask Whether to finish the task associated with this Activity.
*
* @return Returns true if the activity successfully finished, or false if it is still running.
*/
@Override
public final boolean finishActivity(IBinder token, int resultCode, Intent resultData,
int finishTask) {
// Refuse possible leaked file descriptors
if (resultData != null && resultData.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}

synchronized(this) {
ActivityRecord r = ActivityRecord.isInStackLocked(token);
if (r == null) {
return true;
}
// Keep track of the root activity of the task before we finish it
TaskRecord tr = r.getTask();
ActivityRecord rootR = tr.getRootActivity();
if (rootR == null) {
Slog.w(TAG, "Finishing task with all activities already finished");
}
// Do not allow task to finish if last task in lockTask mode. Launchable priv-apps can
// finish.
if (mLockTaskController.activityBlockedFromFinish(r)) {
return false;
}

if (mController != null) {
// Find the first activity that is not finishing.
ActivityRecord next = r.getStack().topRunningActivityLocked(token, 0);
if (next != null) {
// ask watcher if this is allowed
boolean resumeOK = true;
try {
resumeOK = mController.activityResuming(next.packageName);
} catch (RemoteException e) {
mController = null;
Watchdog.getInstance().setActivityController(null);
}

if (!resumeOK) {
Slog.i(TAG, "Not finishing activity because controller resumed");
return false;
}
}
}
final long origId = Binder.clearCallingIdentity();
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 = mStackSupervisor.removeTaskByIdLocked(tr.taskId, false,
finishWithRootActivity, "finish-activity");
if (!res) {
Slog.i(TAG, "Removing task failed to finish activity");
}
} else {

//走这里
res = tr.getStack().requestFinishActivityLocked(token, resultCode,
resultData, "app-request", true);
if (!res) {
Slog.i(TAG, "Failed to finish by app-request");
}
}
return res;
} finally {
Binder.restoreCallingIdentity(origId);
}
}
}
  • com.android.server.am.ActivityStack#requestFinishActivityLocked
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* @return Returns true if the activity is being finished, false if for
* some reason it is being left as-is.
*/
final boolean requestFinishActivityLocked(IBinder token, int resultCode,
Intent resultData, String reason, boolean oomAdj) {
ActivityRecord r = isInStackLocked(token);
if (DEBUG_RESULTS || DEBUG_STATES) Slog.v(TAG_STATES,
"Finishing activity token=" + token + " r="
+ ", result=" + resultCode + ", data=" + resultData
+ ", reason=" + reason);
if (r == null) {
return false;
}

finishActivityLocked(r, resultCode, resultData, reason, oomAdj);
return true;
}
  • ActivityStack#finishActivityLocked
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/**
* @return Returns true if this activity has been removed from the history
* list, or false if it is still in the list and will be removed later.
*/
final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData,
String reason, boolean oomAdj, boolean pauseImmediately) {
if (r.finishing) {
Slog.w(TAG, "Duplicate finish request for " + r);
return false;
}

mWindowManager.deferSurfaceLayout();
try {
r.makeFinishingLocked(); //将Ativity对应的finishing属性置为true
final TaskRecord task = r.getTask();
EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
r.app != null ? r.app.pid : 0, System.identityHashCode(r),
task.taskId, r.shortComponentName, reason); //打印event log
final ArrayList<ActivityRecord> activities = task.mActivities;
final int index = activities.indexOf(r);
if (index < (activities.size() - 1)) { //如果要finish的Activity不是task顶部的Activity
task.setFrontOfTask();
if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
// If the caller asked that this activity (and all above it)
// be cleared when the task is reset, don't lose that information,
// but propagate it up to the next activity.
ActivityRecord next = activities.get(index+1);
next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
}
}

r.pauseKeyDispatchingLocked();

adjustFocusedActivityStack(r, "finishActivity"); //调整focus activityStack(当前stack 调用topRunningActivityLocked为null,即当前stack中的所有task中的Activity没有正在running的,那么此Activity不能再做前台,要移到后面)

finishActivityResultsLocked(r, resultCode, resultData); //如果要finish的Activity有resultTo,向其传递result

final boolean endTask = index <= 0 && !task.isClearingToReuseTask(); //是否要销毁task(当要销毁的Activity在task中的index<=0)
final int transit = endTask ? TRANSIT_TASK_CLOSE : TRANSIT_ACTIVITY_CLOSE;
if (mResumedActivity == r) {
if (DEBUG_VISIBILITY || DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
"Prepare close transition: finishing " + r);
if (endTask) {
mService.mTaskChangeNotificationController.notifyTaskRemovalStarted(
task.taskId);
}
mWindowManager.prepareAppTransition(transit, false);

// Tell window manager to prepare for this one to be removed.
r.setVisibility(false);

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, null, pauseImmediately); //调用startPausingLocked,finish之前需要先pause,注意resuming为null
}

if (endTask) {
mService.getLockTaskController().clearLockedTask(task);
}
} else if (!r.isState(PAUSING)) { //这种情况是finish的不是resumed Activity的情况
// If the activity is PAUSING, we will complete the finish once
// it is done pausing; else we can just directly finish it here.
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish not pausing: " + r);
if (r.visible) {
prepareActivityHideTransitionAnimation(r, transit);
}

final int finishMode = (r.visible || r.nowVisible) ? FINISH_AFTER_VISIBLE
: FINISH_AFTER_PAUSE;
final boolean removedActivity = finishCurrentActivityLocked(r, finishMode, oomAdj,
"finishActivityLocked") == null; //也是调用finishCurrentActivityLocked

// The following code is an optimization. When the last non-task overlay activity
// is removed from the task, we remove the entire task from the stack. However,
// since that is done after the scheduled destroy callback from the activity, that
// call to change the visibility of the task overlay activities would be out of
// sync with the activitiy visibility being set for this finishing activity above.
// In this case, we can set the visibility of all the task overlay activities when
// we detect the last one is finishing to keep them in sync.
if (task.onlyHasTaskOverlayActivities(true /* excludeFinishing */)) {
for (ActivityRecord taskOverlay : task.mActivities) {
if (!taskOverlay.mTaskOverlay) {
continue;
}
prepareActivityHideTransitionAnimation(taskOverlay, transit);
}
}
return removedActivity;
} else {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish waiting for pause of: " + r);
}

return false;
} finally {
mWindowManager.continueSurfaceLayout();
}
}
  • 总的流程

2.onDestory 做了什么?

onDestory主要是进行资源回收,把还在占用的资源释放,里面有很多close。

onDestory 回调方法也是由AMS发出 的 ClientTransaction 消息,然后主线程的looper处理这个消息,通过 transaction.getLifecycleStateRequest() 获知是 DestroyActivityItem ,最后就一步步调用到onDestory了。

调用过程如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
onDestroy():95, MainActivity
performDestroy():7395, Activity (android.app)

// 转发
callActivityOnDestroy(Activity):1306, Instrumentation (android.app)
performDestroyActivity(IBinder, boolean, int, boolean, String):4443, ActivityThread (android.app)
handleDestroyActivity(IBinder, boolean, int, boolean, String):4476, ActivityThread (android.app)
execute(ClientTransactionHandler, IBinder, PendingTransactionActions):39, DestroyActivityItem (android.app.servertransaction)

// 获取是 DestroyActivityItem ,然后交给上面处理
executeLifecycleState(ClientTransaction):145, TransactionExecutor (android.app.servertransaction)

//处理
execute(ClientTransaction):70, TransactionExecutor (android.app.servertransaction)

//这个是由主线程默认的内部Hander H 来处理的
handleMessage(Message):1808, ActivityThread$H (android.app)

// 分发到目标Hander处理
dispatchMessage(Message):106, Handler (android.os)

//looper在这里死循环 ,等到一个AMS发出 的 ClientTransaction 消息
//是怎么收到了呢?是AMS跨进程发送的,然后native收到消息,向上发送。
//在MessagQueue的nativeInit会关联native层的NativeLooper和NativeMessagQueue
loop():193, Looper (android.os)
main(String[]):6669, ActivityThread (android.app)
invoke(Object, Object[]):-1, Method (java.lang.reflect)
run():493, RuntimeInit$MethodAndArgsCaller (com.android.internal.os)
main(String[]):858, ZygoteInit (com.android.internal.os)

再来看下

  • android.app.Activity#onDestroy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
protected void onDestroy() {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onDestroy " + this);
mCalled = true;

// dismiss any dialogs we are managing.
// 取消所有的 dialogs
if (mManagedDialogs != null) {
final int numDialogs = mManagedDialogs.size();
for (int i = 0; i < numDialogs; i++) {
final ManagedDialog md = mManagedDialogs.valueAt(i);
if (md.mDialog.isShowing()) {
md.mDialog.dismiss();
}
}
mManagedDialogs = null;
}

// close any cursors we are managing.
// 关闭所有的cursors
synchronized (mManagedCursors) {
int numCursors = mManagedCursors.size();
for (int i = 0; i < numCursors; i++) {
ManagedCursor c = mManagedCursors.get(i);
if (c != null) {
c.mCursor.close();
}
}
mManagedCursors.clear();
}

// Close any open search dialog
// 关闭
if (mSearchManager != null) {
mSearchManager.stopSearch();
}

if (mActionBar != null) {
// 有ActionBar,调用onDestroy
mActionBar.onDestroy();
}

//最后交给Application dispatch
getApplication().dispatchActivityDestroyed(this);
}
  • android.app.Application#dispatchActivityDestroyed
1
2
3
4
5
6
7
8
9
void dispatchActivityDestroyed(Activity activity) {
// 通知和回调所有的 callbacks。如果有注册了ActivityLifecycleCallbacks
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i=0; i<callbacks.length; i++) {
((ActivityLifecycleCallbacks)callbacks[i]).onActivityDestroyed(activity);
}
}
}
  • 可以通过 android.app.Application#registerActivityLifecycleCallbacks 注册destroye callbacks

基本到这里onDestroy 就是已经做完了。

再次总结

  • finish 主动调用,activity栈中就没有这个了,再也不能返回到这个activity。但是这个activity实例对象还在堆中
  • onDestory AMS回调,调用,比如上滑关闭Activity,比如手动调用finish引发onDestory。onDestroy只是关闭这个Activity对象 持有的一些系统资源。但是这个activity实例对象还在堆中
  • 存在内存泄漏问题?就是上面的finish和onDestory 做完之后,这个activity实例对象还在堆中,还要等待GC的到来,但是,但是, 如果我们在其它地方错误的保留了一个对该activity实例的引用,间接或直接的引用,就会发生内存泄漏。就算你走完了finish和onDestory。最常见错误的就是 在Activity 中 保留了某一个单列的引用

来源及感谢

Activity相关学习-finish activity https://www.jianshu.com/p/f3dbf635f2c4