3-Activity 生命周期

总结

startSpecificActivityLocked ——> realStartActivityLocked 设置 LaunchActivityItem 和 ResumeActivityItem——> IApplicationThread. scheduleTransaction ()

sendMessage ——> EXECUTE_TRANSACTION (也是打开 activity 的 H)——>execute——> executeCallbacks (onCreate)——>cycleToPath (onStart )——>performLifecycleSequence ——>handleResumeActivity ——> onResume

AMS

[[2-Activity进程启动流程#第二步]]

startActivity

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
final boolean realStartActivityLocked (ActivityRecord r, ProcessRecord app,
boolean andResume, boolean checkConfig) throws RemoteException {

......

// 1. addCallback ()
final ClientTransaction clientTransaction = ClientTransaction.obtain (app. thread,
r.appToken);
clientTransaction.addCallback (LaunchActivityItem.obtain (new ...


// 2. setLifecycleStateRequest
final ActivityLifecycleItem lifecycleItem;
if (andResume) {
lifecycleItem = ResumeActivityItem.obtain (mService.isNextTransitionForward ());
} else {
lifecycleItem = PauseActivityItem.obtain ();
}
clientTransaction.setLifecycleStateRequest (lifecycleItem);

// 3. 调用 ClientLifecycleManager.scheduleTransaction ()
mService.getLifecycleManager (). scheduleTransaction (clientTransaction);
......
return true;
}

  1. addCallback() 传入的参数是 LaunchActivityItem , 正是 ClientTransactionItem 的实现类。
  2. setLifecycleStateRequest 表示当前的 ClientTransaction 执行之后应该处于的最终生命周期状态 (ResumeActivityItem)。
  3. mService.getLifecycleManager() 返回的是 ClientLifecycleManager 对象,是 Android 9.0 新增的辅助处理生命周期的类。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 > ClientLifecycleManager.java

void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
final IApplicationThread client = transaction.getClient(); // -> ApplicationThread
transaction.schedule(); // ClientTransaction
if (!(client instanceof Binder)) {
// If client is not an instance of Binder - it's a remote call and at this point it is
// safe to recycle the object. All objects used for local calls will be recycled after
// the transaction is executed on client in ActivityThread.
transaction.recycle();
}
}

> ClientTransaction.java

public void schedule() throws RemoteException {
// 调用 ActivityThread.ApplicationThread.scheduleTransaction()
mClient.scheduleTransaction(this);
}

首先明确一点,到目前为止的方法调用都处于 AMS 所在进程,并不是我们的应用进程,会调用到 App 的 ApplicationThread

回到 App

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private class ApplicationThread extends IApplicationThread.Stub {
......
@Override
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
// 这里调用的是父类 ClientTransactionHandler 的 scheduleTransaction() 方法
ActivityThread.this.scheduleTransaction(transaction);
}
......
}

> ClientTransactionHandler.java

void scheduleTransaction(ClientTransaction transaction) {
transaction.preExecute(this);java
// sendMessage() 方法在 ActivityThread类中实现
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}

H 类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class H extends Handler {

public void handleMessage(Message msg) {
......
case EXECUTE_TRANSACTION:
final ClientTransaction transaction = (ClientTransaction) msg.obj;
// 执行 TransactionExecutor.execute()
mTransactionExecutor.execute(transaction);
if (isSystem()) {
transaction.recycle();
}
break;
......
}
}

TransactionExecutor

1
2
3
4
5
public void execute (ClientTransaction transaction) {          
executeCallbacks (transaction);
// 执行生命周期状态
executeLifecycleState (transaction);
}

addCallback () >>> executeCallbacks ()
setLifecycleStateRequest >>> executeLifecycleState ()

executeCallbacks () 会执行 addCallback () 方法添加的生命周期回调。当前添加的是 LaunchActivityItem

executeLifecycleState () 方法会将当前生命周期同步到 setLifecycleStateRequest () 方法设置的生命周期状态。当前设置的是 ResumeActivityItem

onCreate

TransactionExecutor.executeCallbacks

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
> TransactionExecutor. java

public void executeCallbacks (ClientTransaction transaction) {
final List<ClientTransactionItem> callbacks = transaction.getCallbacks ();

......

final int size = callbacks.size ();
for (int i = 0; i < size; ++i) {
final ClientTransactionItem item = callbacks.get (i);
......
item.execute (mTransactionHandler, token, mPendingActions);
item.postExecute (mTransactionHandler, token, mPendingActions);
......
}
}

调用 XXXActivityItem 的 execute () 和 postExecute () 方法。例如:LaunchActivityItem、ActivityResultItem 等等,execute () 方法中会 Binder 调用 ActivityThread 中对应的 handleXXXActivity () 方法,performXXXXActivity

performLaunchActivity

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
> ActivityThread.java

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;

// 获取 Context
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;

java.lang.ClassLoader cl = appContext.getClassLoader();
// 反射创建 Activity
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);

// 获取 Application系统永远不会直接终止 Activity 以释放内存,而是会终止 Activity 所在的进程。系统不仅会销毁 Activity,还会销毁在该进程中运行的所有其他内容。
if (activity != null) {

activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embedded // 获取 Context
CID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback);


int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
// 设置主题
activity.setTheme(theme);
}

activity.mCalled = false;
// 执行 onCreate()
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
r.activity = activity;
}
r.setState(ON_CREATE);

mActivities.put(r.token, r);


return activity;
}

callActivityOnCreate >>> performCreate >>> 最后调用 onCreate

onResume

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
> TransactionExecutor.java

private void executeLifecycleState(ClientTransaction transaction) {
final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
if (lifecycleItem == null) {
// No lifecycle request, return early.
return;
}

......

// Cycle to the state right before the final requested state.
cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */);

// Execute the final transition with proper parameters.
lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
}

现在是 ResumeActivityItem,方法体内直接调用其 execute() 方法。和 onCreate() 的套路是一模一样的,调用 ActivityThread.handleResumeActivity() ,接着是 Instrumentation.callActivityOnResume() ,最后回调 Activity.onResume()

onStart

cycleToPath

正常的生命周期流程应该是 onCreate () -> onStart () -> onResume () ,但是代码中好像又没有显示调用。其实是在 executeLifecycleState () 中的 cycleToPath () 方法中做了生命周期的同步。简单说就是,当前处于 onCreate () 状态,setLifecycleState () 设置的 final stateonResume () ,就需要执行 onCreate 到 onResume 之间的状态,即 onStart ()

getLifecyclePath 计算出中间的生命周期

unknown_filename.30|600|600

onPause

在 resumeTopActivityInnerLocked 中会先对 resume 状态的 activity 执行 pause。

为什么 Activity.finish() 之后 10s 才 onDestroy ?

Activity 的 onStop/onDestroy 是依赖 IdleHandler 来回调的,正常情况下当主线程空闲时会调用。但是由于某些特殊场景下的问题,导致主线程迟迟无法空闲,onStop/onDestroy 也会迟迟得不到调用。但这并不意味着 Activity 永远得不到回收,系统提供了一个兜底机制,当 onResume 回调 10s 之后,如果仍然没有得到调用,会主动触发。

虽然有兜底机制,但无论如何这肯定不是我们想看到的。如果我们项目中的 onStop/onDestroy 延迟了 10s 调用,该如何排查问题呢?可以利用 Looper.getMainLooper().setMessageLogging() 方法,打印出主线程消息队列中的消息。每处理一条消息,都会打印如下内容:

1
2
logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what);
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);

另外,由于 onStop/onDestroy 调用时机的不确定性,在做资源释放等操作的时候,一定要考虑好,以避免产生资源没有及时释放的情况。
不要做耗时操作,例如:循环动画

是谁指挥着 onStop/onDestroy 的调用?

在 Activity 跳转过程中,为了保证流畅的用户体验,只要前一个 Activity 与用户不可交互,即 onPause() 被回调之后,下一个 Activity 就要开始自己的生命周期流程了。所以 onStop/onDestroy 的调用时间是不确定的,甚至像文章开头的例子中,整整过了 10s 才回调。那么,到底是由谁来驱动 onStop/onDestroy 的执行呢?我们来看看下一个 Activity 的 onResume 过程。

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
> ActivityThread.java

public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
String reason) {
......
// 回调 onResume
final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
......
final Activity a = r.activity;
......
if (r.window == null && !a.mFinished && willBeVisible) {
......
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
// 添加 decorView 到 WindowManager
wm.addView(decor, l);
} else {
a.onWindowAttributesChanged(l);
}
}
} else if (!willBeVisible) {
......
}
......

// 主线程空闲时会执行 Idler
Looper.myQueue().addIdleHandler(new Idler());
}

IdleHandler

在完成最终的界面绘制和显示之后,有这么一句代码 Looper.myQueue().addIdleHandler(new Idler())IdleHandler 不知道大家是否熟悉,它提供了一种机制,当主线程消息队列空闲时,会执行 IdleHandler 的回调方法。至于怎么算 “空闲”,我们可以看一下 MessageQueue.next() 方法。

[[IdleHandler]]

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
> MessageQueue.java

Message next() {
......
int pendingIdleHandlerCount = -1;
int nextPollTimeoutMillis = 0;
for (;;) {
// 阻塞方法,主要是通过 native 层的 epoll 监听文件描述符的写入事件来实现的。
// 如果 nextPollTimeoutMillis = -1,一直阻塞不会超时。
// 如果 nextPollTimeoutMillis = 0,不会阻塞,立即返回。
// 如果 nextPollTimeoutMillis > 0,最长阻塞nextPollTimeoutMillis毫秒(超时),如果期间有程序唤醒会立即返回。
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {
// msg.target == null表示此消息为消息屏障(通过postSyncBarrier方法发送来的)
// 如果发现了一个消息屏障,会循环找出第一个异步消息(如果有异步消息的话),所有同步消息都将忽略(平常发送的一般都是同步消息)
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
if (msg != null) {
if (now < msg.when) {
// 消息触发时间未到,设置下一次轮询的超时时间
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// 得到 Message
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
msg.markInUse(); // 标记 FLAG_IN_USE
return msg;
}
} else {
nextPollTimeoutMillis = -1;
}
......

/*
* 两个条件:
* 1. pendingIdleHandlerCount = -1
* 2. 此次取到的 mMessage 为空或者需要延迟处理
*/
if (pendingIdleHandlerCount < 0
&& (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
if (pendingIdleHandlerCount <= 0) {
// 没有 idle handler 需要运行,继续循环
mBlocked = true;
continue;
}

if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}

// 下一次 next 时,pendingIdleHandlerCount 又会被置为 -1,不会导致死循环
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null; // release the reference to the handler

boolean keep = false;
try {
// 执行 Idler
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf(TAG, "IdleHandler threw exception", t);
}

if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}

// 将 pendingIdleHandlerCount 置零
pendingIdleHandlerCount = 0;
nextPollTimeoutMillis = 0;
}
}

  • 在正常的消息处理机制之后,额外对 IdleHandler 进行了处理。当本次取到的 Message 为空或者需要延时处理的时候,就会去执行 mIdleHandlers 数组中的 IdleHandler 对象。其中还有一些关于 pendingIdleHandlerCount 的额外逻辑来防止循环处理。
  • 当新的 Activity 完成页面绘制并显示之后,主线程就可以停下歇一歇,来执行 IdleHandler 了。再回来 handleResumeActivity() 中来,Looper.myQueue().addIdleHandler(new Idler()) ,这里的 IdlerIdleHandler 的一个具体实现类。
  • 最后获取要 stop 的 Activity,该 stop 的 stop,该 destroy 的 destroy

stop 和 destroy 系统10s兜底

在 ActivityRecord.completeResumeLocked 会在 activity resume 之后调用,在这个方法中会调用
ActivityStackSuperVisor.scheduleIdleTimeoutLocked(),即使主线程迟迟没有机会执行 Idler,系统仍然提供了兜底机制,防止已经不需要的 Activity 长时间无法被回收,从而造成内存泄漏等问题。
`

1
2
3
4
5
6
7
> ActivityStackSuperVisor.java

void scheduleIdleTimeoutLocked(ActivityRecord next) {
Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG, next);
mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT); //IDLE_TIMEOUT= 10*1000
}

总结

应用进程发起请求 -> AMS 处理请求(对 Activity 发起 pause 生命周期) -> 应用进程处理 pause 生命周期 (处理完成后通知 AMS) -> AMS 预处理 finishing 的 Activity (将 Activity 添加至 stop 队列中,开启一个 10s 延迟任务) -> AMS resume 一个新的 Activity -> 应用进程执行新 Activityresume 生命周期,完成后开启一个 IdleHandler (IdleHandler 执行时会通知 AMS) -> AMS 处理 stop 列表中的 Activity (首先清除前面的延迟任务,然后发送 destory 生命周期到应用进程)-> 应用进程处理 destroy 生命周期。


3-Activity 生命周期
http://peiniwan.github.io/2024/04/206fa974f82b.html
作者
六月的雨
发布于
2024年4月6日
许可协议