---
title: 'AndroidThread - App 進程'
disqus: kyleAlien
---
AndroidThread - App 進程
===
## OverView of Content
進程(Process)的概念是,程序的運行實例(簡單理解:一個應用就是一個進程)
線程(Thread)是 CPU 調度的基礎單位
這裡還會涉及到 [**Android Handler**](https://hackmd.io/7fBX6uEtQt6AzCpuBWTHMQ?view) 有在另外一篇文章說過
[TOC]
## 概述
一個應用的入口一般來說都是 main 函數(一切的起源),main 函數主要也做了這些事
1. 初始化
比如 Window 環境下就要創建窗口、像系統申請資源
2. **進入死循環**
若在循環中接收到事件則處理,**一直到這個應用進程退出**
一般來說我們會透過 IDE + SDK 開發程序,這相對的會簡單許多,就像是 Android **若是你不了解其中內容你會以為 4 大零組件(Activity、Server、ContentProvider、Broadcast)就是進程**
### AndroidManifest
* 從 AndroidManifest.xml 中就可以看到啟動 Activity 的足跡
```xml=
<!-- 四大零組件只是組成 Application 的一部分 -->
<application
android:name=".application.BwingApplication"
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name">
<activity android:name=".ui.activity.boot.BootActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
```
* **若非特別聲明,所有個組件都運行在當前進程**
> Server 就滿常運行在其他進程
## 觀察 - 進程&線程
一個應用進程一次只會啟動一個線程 ? 主要進程由哪個進程啟動
* 切換到 debug 模式,並且開啟 [**線程監聽欄位**](https://developer.android.com/studio/debug#startdebug)
* 使用 `Thread.activeCount()` 也可以看到當前線程的數量
### 啟動 Acitivty - [ActivityThread](https://cs.android.com/android-studio/platform/tools/base/+/mirror-goog-studio-main:fakeandroid/srcs/android/app/ActivityThread.java)
* 啟動入口 Activity,並觀察 Threads 列表
```java=
public class BootActivity extends BaseActivity {
private static final String TAG = BootActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
// 斷點設定在 super.onCreate
super.onCreate(savedInstanceState);
}
}
```
> 
* 從上圖 `Thread stack` 可以發現幾件事情
1. [**ActivityThread**](https://cs.android.com/android-studio/platform/tools/base/+/mirror-goog-studio-main:fakeandroid/srcs/android/app/ActivityThread.java):除了 MainThread 之外還會啟動其他線程;而 **==MainThread 由 ZygoteInit 啟動== (`com.android.internal.os`),經過一系列的調用後才會到 Activity**
```java=
// ActivityThread.java
public static void main(String[] args) {
...
// 主線程才能調用該函數
Looper.prepareMainLooper();
...
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
// 主線程對應的 Thread
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
```
2. 另外啟動了 4 個 BinderThread 用於與 Binder 通訊 (留到另外一個章節在說)
> 
### 啟動 Server
* 創建一個簡單的 Server,並將它啟動,再來觀察線程的狀態,是否也會有許多線程
```java=
public class TimedTaskService extends Service {
@Override
public void onCreate() {
// 斷點設定在 super.onCreate
super.onCreate();
}
}
```
> 
* 從上面可以發現
1. **Server 也是由 ==ZygoteInit 啟動==** (`com.android.internal.os`),啟動流程與 Activity 一致,都是由 **Activity Thread 啟動**
> 
2. **Binder 線程並不是 Activity 獨有,Server 也啟動了 4 個 Binder 線程**
> 
### 啟動兩個 Activity
* 啟動 另一個 Activity (LobbyActivity) 並且不結束 BootActivity (也就是將 BootActivity 壓入 Activity 棧中)
```java=
// 第一個 Activity
public class BootActivity extends BaseActivity {
private static final String TAG = BootActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = new Intent(this, LobbyActivity.class);
startActivity(intent);
}
}
//----------------------------------------------------------------------
// 第二個 Activity
public class LobbyActivity extends BaseActivity {
private static final String TAG = LobbyActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
// 斷點設定在 super.onCreate
super.onCreate(savedInstanceState);
}
}
```
> 
* 上圖可以發現幾個現象
1. LobbyActivity 被執行時,**MainThread (ActivityThread) 仍只有一個 (當前應用的 ActivityThread 號碼為 8186)**
> 
2. 上一個 BootActivity 暫時退出運行
3. Binder 線程數量相同
> 
### 2 個 Activity 相同進程 - 證明
* 證明 BootActivity、LobbyActivity 在同一個進程
```java=
// 第一個 Activity
public class BootActivity extends BaseActivity {
private static final String TAG = BootActivity.class.getSimpleName();
public static int TEST = 1; // Default = 1
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = new Intent(this, LobbyActivity.class
// 在啟動 LobbyActivity 之前修改 TEST 為 2,若是不同進程,則 LobbyActivity 就不能取到改變後 TEST 的數值
TEST = 2;
Log.w("TEST_PROCESS" , "BootActivity TEST value: " + TEST);
startActivity(intent);
}
}
// 第二個 Activity
public class LobbyActivity extends BaseActivity {
private static final String TAG = LobbyActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.w("TEST_PROCESS" , "BootActivity TEST value: " + BootActivity.TEST);
}
}
```
* 以下可以證明,這兩個 Activity 是運行在同一個進程
1. 在啟動 LobbyActivity 之前修改 TEST 為 2; 若是不同進程,則 LobbyActivity 就會只會拿到初始值,也就是 1
> 
2. 從 Logcat 可以輸出查看:PID(Process id)、TID (Thread id) 也是相同的
> Locat 格式:29806(pid)-2986(Thread id),[**參考 stackoverflow**](https://stackoverflow.com/questions/41607956/explanation-about-logcat)
:::success
* 補充
也可以讓不同 APK 包裡面的組件運行在相同的進程當中,這樣不同組件還可以相互分享資源
:::
## [ActivityThread](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/app/ActivityThread.java) 概述
對於一個應用來說,ActivityThread#main 就是 App 的進入口
:::success
* 誰呼叫 ActivityThread#main ?
Zygote 服務 fork 出一個新的 App 進程後,就會 **透過反射呼叫到 `ActivityThread #main` 方法**,詳細可以參考 [**Zygote 分析**](https://hackmd.io/Yw1s2x32QoqawvOsW039ZA?view#Zygote-%E9%80%B2%E7%A8%8B)
:::
```java=
// ActivityThread.java
// final 類
public final class ActivityThread extends ClientTransactionHandler
implements ActivityThreadInternal {
public static void main(String[] args) {
...
Looper.prepareMainLooper();
...
// 創建一個 ActivityThread 對象
ActivityThread thread = new ActivityThread();
// @ 之後分析 attach 方法
thread.attach(false, startSeq);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
...
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
}
```
### ActivityThread - 創建 [Looper](https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/os/Looper.java) & Handler
* MainLooper 與一般的 prepare 差不多,只差在 **ActivityThread 有對 Main Looper 的管理**
1. **主線程的 Looper 不可以退出,並把它存在靜態變量中**
2. 任何線程都可以透過 getMainLooper() 取得 Main Looper 對象
3. Main Looper 也可以隨時取得當前線程的 Looper
```java=
// ActivityThread.java
public final class ActivityThread {
private static Looper sMainLooper;
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
public static void prepareMainLooper() {
// 1. 該 Looper 不允許退出
// @ 追蹤 prepare 方法
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper(); // myLooper 可以透過 TheadLocal 獲得 Looper 對象
}
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
// 如果 Looper 已經創建過,則拋出錯誤
// 一個 thread 對應一個 Looper
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
// 2. 取得 Main Looper 對象
public static Looper getMainLooper() {
synchronized (Looper.class) {
return sMainLooper;
}
}
// 3. 隨時取得當前線程的 Looper
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
}
```
* ActivityThread 的 Handler 是使用內部類 H class,創建處理消息的對象
```java=
// ActivityThread.java
public final class ActivityThread {
// 建構 Handler
final H mH = new H();
class H extends Handler {
@Override
public void handleMessage(Message msg) {
// 為各種消息做不同處理
switch (msg.what) {
...
}
}
}
final Handler getHandler() {
return mH;
}
}
```
* 循環處理消息 [**Looper**](https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/os/Looper.java) 的 `loop` 方法,這邊要注意一下 `loop` 是 **靜態方法,所以只能訪問靜態的數據**
:::info
Looper 主要的工作就是從 MessageQueue 中取得消息,並分發給相關的負責人(Handler),**若消息隊列為空,它就很可能會進入睡眠,並讓出 CPU 資源**
:::
```java=
// Looper.java
public static void loop() {
// 由於是靜態函數,所以必須透過 myLooper 來獲取 Loop 對象
final Looper me = myLooper();
...
// 每個 Looper 內都有一個 MessageQueue 對象
final MessageQueue queue = me.mQueue;
...
// 開始無限倫循
for (;;) {
Message msg = queue.next(); // 若沒有下一個訊息則會阻塞(wait)
if (msg == null) {
// 若當前隊列中沒有 msg 則說明該線程準備要退出了
return; // 跳出無限循環迴圈
}
...
try {
// target 就是 Handler,到了這裡就開始分發訊息
// 在這裡就是將消息發送給 H class
msg.target.dispatchMessage(msg);
...
}
...
msg.recycleUnchecked(); // 消除處理完畢,回收
}
}
```
* Binder IPC 事件就會透過 Handler 將消息傳送到 Main Thread 中
> 
### [ActivityThread](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/app/ActivityThread.java) - 呼叫 AMS 啟動 Activity
從 ActivtyThread#**attach** 方法開始分析
```java=
// ActivtyThread.java
// main 呼叫 attach 方法
private void attach(boolean system, long startSeq) {
if (!system) {
// 取得 AMS 通訊代理
final IActivityManager mgr = ActivityManager.getService();
try {
// 呼叫 AMS#attachApplication 方法
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
... 省略部份
} else {
... SystemService 進程才會走到這
}
...
}
```
* 這裡從 AMS 開始會接觸到許多類,先看類的功能、關係再追蹤程式碼
* 先看看類的簡介
| 類 | 概述 | 說明 |
| -------- | -------- | - |
| IApplicationThread | 使用者接口 | 作為 App 應用的服務端,讓系統服務回調 |
| ActivtyManagerService | 系統服務 | 使用者訪問的入口 |
| ActivityTaskManagerInternal | 抽象類 | 定義 ActivityTask 的相關方法 |
| LocalService | ActivityTaskManagerService內 部類 | 實際上會調用 ActivityTaskManagerService 服務 |
| RootWindowContainer | Window 容器 | |
| ActivityTaskManagerService | 系統服務 | Task 管理服務 |
| ActivityTaskSupervisor | - | 負責與 `ActivityTaskManagerService` 通訊 |
| ClientLifecycleManager | 管理使用者端生命週期 | |
| ClientTransaction | AIDL 傳輸類 | 內部存有使用者 `IApplicationThread` 接口 |
* AMS 相關類的 UML
> 
* ActivtyThread#attach 主要會分為 SystemService 呼叫、一般 App 呼叫(目前是這個情況),一般 App 又會透過 Binder 代理呼叫 [**AMS**](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java)#`attachApplication` 方法
1. AMS#**attachApplication** 方法:我們主要看 `attachApplicationLocked` 方法,這個方法很長主要有兩個重點
* IApplicationThread#**binderApplication** 方法:IApplicationThread 是由最一開始 App 進程傳入,該方法 **主要目的是將 App 的 ==ApplicationThread 與 ActiivtyThreadServer 綁定==**
* [**ActivityTaskManagerInternal**](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java)#**attachApplication** 方法:**啟動 App 的 Activity**
```java=
// ActivityManagerService.java
public ActivityTaskManagerInternal mAtmInternal;
@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
// 判斷是否有返回的 IApplicationThread
if (thread == null) {
throw new SecurityException("Invalid application interface");
}
synchronized (this) {
int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread,
callingPid, // 呼叫者 pid
callingUid, // 呼叫者 uid
startSeq);
Binder.restoreCallingIdentity(origId);
}
}
private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
int pid, int callingUid, long startSeq) {
ProcessRecord app; // 取得該 App 訊息
... 省略部份
try {
... 省略部份
if (app.getIsolatedEntryPoint() != null) {
...
} else if (instr2 != null) {
// 與 AMS 綁定
thread.bindApplication(processName, appInfo, providerList,
instr2.mClass,
profilerInfo, instr2.mArguments,
instr2.mWatcher,
instr2.mUiAutomationConnection, testMode,
/*省略部份參數*/ );
} else {
// 與 AMS 綁定
thread.bindApplication(processName, appInfo, providerList, null, profilerInfo, /*省略部份參數*/);
}
... 省略部份
} /* 省略 catch */
if (normalMode) {
try {
// @ 追蹤 attachApplication 方法
didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
} /* 省略 catch */
}
... 省略部份
return true;
}
```
> 
2. 分析 ActivityTaskManagerService#attachApplication 方法:ActivityTaskManagerInternal 是一個抽象類,它的實做在 [**ActivityTaskManagerService**](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java)
:::info
在這裡 ActivityTaskManagerService 的功能就是與 RootWindowContainer 通訊的橋樑
:::
```java=
// ActivityTaskManagerService.java
public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
RootWindowContainer mRootWindowContainer;
final ActivityTaskManagerInternal mInternal;
public ActivityTaskManagerService(Context context) {
...
mInternal = new LocalService();
}
final class LocalService extends ActivityTaskManagerInternal {
... 省略其他方法
@Override
public boolean attachApplication(WindowProcessController wpc) throws RemoteException {
synchronized (mGlobalLockWithoutBoost) {
... 省略 trace
try {
// @ 追蹤 attachApplication 方法
return mRootWindowContainer.attachApplication(wpc);
} /* 省略 finally */
}
}
}
}
```
3. [**RootWindowContainer**](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java)#attachApplication:取得裝置上目前所有的螢幕,並遍歷 `DisplayContent` 下所有的 rootTask
```java=
// RootWindowContainer.java
ActivityTaskSupervisor mTaskSupervisor;
boolean attachApplication(WindowProcessController app) throws RemoteException {
boolean didSomething = false;
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
mTmpRemoteException = null;
mTmpBoolean = false; // Set to true if an activity was started.
// 取得要顯示的螢幕 DisplayContent
final DisplayContent display = getChildAt(displayNdx);
// 遍歷該 DisplayContent 中所有的 RootTasks
display.forAllRootTasks(rootTask -> {
// 錯誤
if (mTmpRemoteException != null) {
return;
}
// 不可建就忽略
if (rootTask.getVisibility(null /* starting */)
== TASK_FRAGMENT_VISIBILITY_INVISIBLE) {
return;
}
// 在這裡會回調
// @ 追蹤 startActivityForAttachedApplicationIfNeeded 方法
final PooledFunction c = PooledLambda.obtainFunction(
// 重點
RootWindowContainer::startActivityForAttachedApplicationIfNeeded,
this,
PooledLambda.__(ActivityRecord.class),
app,
rootTask.topRunningActivity()
);
rootTask.forAllActivities(c);
c.recycle();
});
if (mTmpRemoteException != null) {
throw mTmpRemoteException;
}
didSomething |= mTmpBoolean;
}
if (!didSomething) {
ensureActivitiesVisible(null, 0, false /* preserve_windows */);
}
return didSomething;
}
private boolean startActivityForAttachedApplicationIfNeeded(ActivityRecord r,
WindowProcessController app, ActivityRecord top) {
... 省略部份
try {
// @ 追蹤 realStartActivityLocked 方法
if (mTaskSupervisor.realStartActivityLocked(r, app,
top == r && r.getTask().canBeResumed(r) /*andResume*/,
true /*checkConfig*/)) {
mTmpBoolean = true;
}
} /* 省略 catch */
return false;
}
```
> 
4. ActivityTaskSupervisor#realStartActivityLocked:真正啟動 Activity,已最終結果來說,AMS 系統服務會透過 App 傳入的 `IApplicationThread` 回掉到 App 端
```java=
// ActivityTaskSupervisor.java
final ActivityTaskManagerService mService;
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
boolean andResume, boolean checkConfig) throws RemoteException {
// 檢查是否全部都完成 Paused
if (!mRootWindowContainer.allPausedActivitiesComplete()) {
... log 訊息
return false;
}
final Task task = r.getTask();
final Task rootTask = task.getRootTask();
...
try {
r.startFreezingScreenLocked(proc, 0);
// 啟動較慢的 App 訊息
r.startLaunchTickingLocked();
// 設定 ActivityRecord 的 proc
r.setProcess(proc);
// Ensure activity is allowed to be resumed after process has set.
if (andResume && !r.canResumeByCompat()) {
andResume = false;
}
... 省略部份
// 如果進程是第一次啟動活動,則將控制器發送到客戶端
// 所以客戶端可以保存從活動中獲取控制器的綁定 事務 服務。
final IActivityClientController activityClientController =
proc.hasEverLaunchedActivity() ? null : mService.mActivityClientController;
r.launchCount++;
r.lastLaunchTime = SystemClock.uptimeMillis();
// 紀錄啟動時間
proc.setLastActivityLaunchTime(r.lastLaunchTime);
...log 訊息
... 省略部份
try {
if (!proc.hasThread()) {
throw new RemoteException();
}
List<ResultInfo> results = null;
List<ReferrerIntent> newIntents = null;
if (andResume) {
// We don't need to deliver new intents and/or set results if activity is going
// to pause immediately after launch.
results = r.results;
newIntents = r.newIntents;
}
...log, event 訊息
if (r.isActivityTypeHome()) {
// 如果是 HomeActivity,就替換 Task 的底部
updateHomeProcess(task.getBottomMostActivity().app);
}
.. 省略部份
// Create activity launch transaction.
// 取得覆用的 ClientTransaction
final ClientTransaction clientTransaction = ClientTransaction.obtain(
proc.getThread(), r.appToken);
final boolean isTransitionForward = r.isTransitionForward();
// 之後到 Client 端會使用到這個 call back
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
System.identityHashCode(r),
r.info, /* 省略部分參數*/ );
// Set desired final state.
final ActivityLifecycleItem lifecycleItem;
if (andResume) {
lifecycleItem = ResumeActivityItem.obtain(isTransitionForward);
} else {
lifecycleItem = PauseActivityItem.obtain();
}
clientTransaction.setLifecycleStateRequest(lifecycleItem);
// ActivityTaskManagerService == mService
// @ 分析 scheduleTransaction 方法
mService.getLifecycleManager().scheduleTransaction(clientTransaction);
... 省略部份
} /* 省略 catch */
} /* 省略 finally */
... 省略部份
return true;
}
// -------------------------------------------------------------
// ActivityTaskManagerService.java
public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
private final ClientLifecycleManager mLifecycleManager;
...
ClientLifecycleManager getLifecycleManager() {
return mLifecycleManager;
}
}
// -------------------------------------------------------------
// ClientLifecycleManager.java
class ClientLifecycleManager {
void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
final IApplicationThread client = transaction.getClient();
transaction.schedule();
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
// AIDL 可傳送類
public class ClientTransaction implements Parcelable, ObjectPoolItem {
private IApplicationThread mClient;
public void schedule() throws RemoteException {
// 呼叫到 Client 端
mClient.scheduleTransaction(this);
}
}
```
> 
### [ActivityThread](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/app/ActivityThread.java) - scheduleTransaction 處理 AMS 資料
到這一步後,代表 AMS 準備啟動 Activity,它會透過最開始對 AMS 傳入的 `IApplicationThread` 來進行回調,並處理 AMS 傳入的 `ClientTransaction`
```java=
// ActivityThread.java
public final class ActivityThread extends ClientTransactionHandler
implements ActivityThreadInternal {
private class ApplicationThread extends IApplicationThread.Stub {
@Override
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
// @ 追蹤 scheduleTransaction
ActivityThread.this.scheduleTransaction(transaction);
}
}
}
```
ActivityThread 相關類 UML
> 
* ActivityThread 繼承 ClientTransactionHandler 類:該用來處理 Binder AMS IPC 回傳的 `ClientTransaction` 對象,並定義 Handler 發送訊息的接口
```java=
// ClientTransactionHandler.java
public abstract class ClientTransactionHandler {
void scheduleTransaction(ClientTransaction transaction) {
transaction.preExecute(this);
// 傳輸 EXECUTE_TRANSACTION
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}
// 由 ActivityThread 實作
abstract void sendMessage(int what, Object obj);
}
```
* 回到 ActivityThread 類,它會實做 ClientTransactionHandler#sendMessage 方法,並 **透過 Handler 將消息帶回到 Main Thread**
| Handler's what | obj |
| -------- | -------- |
| `H.EXECUTE_TRANSACTION` | `ClientTransaction` |
```java=
// ActivityThread.java
final H mH = new H();
// what => H.EXECUTE_TRANSACTION
// obj => ClientTransaction
void sendMessage(int what, Object obj) {
sendMessage(what, obj, 0, 0, false);
}
private void sendMessage(int what, Object obj, int arg1) {
sendMessage(what, obj, arg1, 0, false);
}
private void sendMessage(int what, Object obj, int arg1, int arg2) {
sendMessage(what, obj, arg1, arg2, false);
}
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
... debug 訊息
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
// 異步消息
if (async) {
msg.setAsynchronous(true);
}
mH.sendMessage(msg);
}
```
* 查看 Handler 如何處理 `EXECUTE_TRANSACTION` 訊息:
1. 透過 TransactionExecutor#execute 處理 `ClientTransaction` 對象
```java=
// ActivityThread.java
private final TransactionExecutor mTransactionExecutor = new TransactionExecutor(this);
class H extends Handler {
public static final int EXECUTE_TRANSACTION = 159;
public void handleMessage(Message msg) {
switch (msg.what) {
case EXECUTE_TRANSACTION:
final ClientTransaction transaction = (ClientTransaction) msg.obj;
// @ 追蹤 execute 方法
mTransactionExecutor.execute(transaction);
if (isSystem()) {
transaction.recycle();
}
break;
}
}
}
```
2. 判斷 ClientTransaction 訊息:處理 AMS 傳給 App 的 `ClientTransaction` 物件,並呼叫 AMS 傳入的 ClientTransaction 的 callback
:::info
* 從這裡可以看出 Destory 的 Activity 是否真的移除(或是說移除的時機),是由 AMS 決定
:::
```java=
// TransactionExecutor.java
private ClientTransactionHandler mTransactionHandler;
public void execute(ClientTransaction transaction) {
... debug 訊息
final IBinder token = transaction.getActivityToken();
if (token != null) {
// 取得已安排被 destory 的 activity
final Map<IBinder, ClientTransactionItem> activitiesToBeDestroyed =
mTransactionHandler.getActivitiesToBeDestroyed();
// 檢查該請求是否是 destory
final ClientTransactionItem destroyItem = activitiesToBeDestroyed.get(token);
if (destroyItem != null) {
if (transaction.getLifecycleStateRequest() == destroyItem) {
// 它將執行將銷毀活動的事務 token,
// 因此可以刪除對應的待銷毀記錄。
activitiesToBeDestroyed.remove(token);
}
if (mTransactionHandler.getActivityClient(token) == null) {
... debug 訊息
return;
}
}
}
... log 訊息
// @ 追蹤 executeCallbacks
executeCallbacks(transaction);
executeLifecycleState(transaction);
mPendingActions.clear();
... debug 訊息
}
```
3. 執行 ClientTransaction's Callback:執行 ClientTransaction#**execute** 方法
```java=
// TransactionExecutor.java
private ClientTransactionHandler mTransactionHandler;
public void executeCallbacks(ClientTransaction transaction) {
final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
if (callbacks == null || callbacks.isEmpty()) {
// No callbacks to execute, return early.
return;
}
...debug 訊息
final IBinder token = transaction.getActivityToken();
ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
... 省略部份
final int size = callbacks.size();
for (int i = 0; i < size; ++i) {
final ClientTransactionItem item = callbacks.get(i);
...省略部份
// 執行 callback
item.execute(mTransactionHandler,
token,
mPendingActions);
item.postExecute(mTransactionHandler,
token,
mPendingActions);
... 省略部份
}
}
```
> 
### [ActivityThread](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/app/ActivityThread.java) - 回調 ClientTransactionItem
ActivityThread 會回調 `ClientTransactionItem`,而 `ClientTransactionItem` 是在 `ActivityTaskSupervisor` 創建(跟 App 不同進程)
* 回顧 AMS 設定 Call Back 的時機
```java=
// Create activity launch transaction. 取得覆用的 ClientTransaction
final ClientTransaction clientTransaction = ClientTransaction.obtain(
proc.getThread(), r.appToken);
// 設定 call back 是 LaunchActivityItem !
clientTransaction.addCallback(
LaunchActivityItem.obtain(new Intent(r.intent),
System.identityHashCode(r),
r.info, /* 省略部分參數*/ );
// Set desired final state.
final ActivityLifecycleItem lifecycleItem;
if (andResume) {
lifecycleItem = ResumeActivityItem.obtain(isTransitionForward);
} else {
lifecycleItem = PauseActivityItem.obtain();
}
clientTransaction.setLifecycleStateRequest(lifecycleItem);
```
* 從上面的簡單回顧我們可以知道 app 進程回調的對象是 [**LaunchActivityItem**](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/app/servertransaction/LaunchActivityItem.java) 類,調用的方法是 ClientTransactionItem#`execute`
```java=
// LaunchActivityItem.java
public class LaunchActivityItem extends ClientTransactionItem {
@Override
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
// 創建 ActivityClientRecord
ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo, /* 省略部份參數 */);
// @ 追蹤 handleLaunchActivity 方法
client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
}
}
```
> 
### performLaunchActivity - 執行 onCreate
* ActivityThread 繼承於 ClientTransactionHandler,所以 `handleLaunchActivity` 方法也由 ActivityThread 實做,該**方法的重點是 `performLaunchActivity`**
```java=
// ActivityThread.java
public final class ActivityThread extends ClientTransactionHandler
implements ActivityThreadInternal {
@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
... 省略部份
// @ 追蹤 performLaunchActivity 方法
final Activity a = performLaunchActivity(r, customIntent);
... 省略部份
return a;
}
}
```
* ActivityThread#performLaunchActivity 方法會分為幾個階段,最終會呼叫到 Activity#onCreate 方法
1. 取得 ActivityInfo、ComponentName、PackageInfo
```java=
// ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
ComponentName component = r.intent.getComponent();
if (component == null) {
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
if (r.activityInfo.targetActivity != null) {
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}
}
```
2. 創建 Activity 還有其對應的 ContextImpl 對象
```java=
// ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;
...
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
... 省略部份
} /* 省略 catch */
...
}
```
3. 從 LoadedApk 取得 Application 對象、呼叫 Activity#attach 方法,透過 Instrumentation#callActivityOnCreate 呼叫到 Activity#onCreate 方法
```java=
// ActivityThread.java
Instrumentation mInstrumentation;
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;
...
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
... 省略部份
if (activity != null) {
... 省略部份
// Context 把 Activity 包裝起來
appContext.setOuterContext(activity);
// 呼叫 Activity#attach 方法
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent, /* 省略部份參數 */);
... 省略部份
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
...
}
r.setState(ON_CREATE);
} /* 省略 catch */
return activity;
}
```
* 最後我們來看 Instrumentation#callActivityOnCreate 是如何呼叫到 Activity#onCreate 方法
```java=
// Instrumentation.java
public void callActivityOnCreate(Activity activity, Bundle icicle) {
prePerformCreate(activity);
// @ 追蹤 performCreate 方法
activity.performCreate(icicle);
postPerformCreate(activity);
}
// ------------------------------------------------------------
// Activity.java
final void performCreate(Bundle icicle) {
performCreate(icicle, null);
}
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
... 省略部份
if (persistentState != null) {
onCreate(icicle, persistentState);
} else {
// @ 追蹤 onCreate
onCreate(icicle);
}
... 省略部份
}
@MainThread
@CallSuper
protected void onCreate(@Nullable Bundle savedInstanceState) {
... 到這一步就進入我們最常見的 onCreate
}
```
加上 Activity、Instrumentation 類,再次整理 UML
> 
## Appendix & FAQ
:::info
:::
###### tags: `Android Framework` `Java 多線程`