なぜメインスレッドはLooper#loop()メソッドのデッドサイクルによって殺されなかったのか
9623 ワード
なぜメインスレッドはLooperにloop法のデッドサイクルカード死一、問題 二、補問 三、Activityライフサイクルフロー 一、問題
問1:メインスレッドはLooperのためloop()はデッドサイクルですが、なぜプライマリスレッドはデッドサイクルカードのために死なないのですか?メインスレッドは確かにデッドサイクルであるが、デッドサイクルを開始する前に
問2:メインラインのデッドサイクルはCPU資源を消耗しているのではないでしょうか?いやいや、ここではLinuxのpipe/epollメカニズムに関し、メインスレッドのメッセージキューにメッセージがない場合、
問3:メインスレッドのメッセージはどこから来ますか.他のスレッドはHandlerを介してプライマリスレッドに送信される
二、補問
問:Androidアプリ起動プロセスは、Activity#onCreate()などのライフサイクルがLooper#loop()のデッドサイクルのために実行されないのはなぜですか.答え:Activityのライフサイクル方法はBinderのプロセス間通信によって実現され、プロセス間通信ではLooper#loop()のデッドサイクルの影響(同じスレッドではない)を受けず、システムプロセスはアプリケーションプロセスにActivityを呼び出すライフサイクル方法を通知します.まずActivity Thread内部のHandler#handleMessage()でスレッドをプライマリスレッドに切り替え、HandlerでActivityのライフサイクルメソッドの呼び出しを完了します.
三、Activityライフサイクルプロセス
プロセス実行(API 26):
問1:メインスレッドはLooperのためloop()はデッドサイクルですが、なぜプライマリスレッドはデッドサイクルカードのために死なないのですか?メインスレッドは確かにデッドサイクルであるが、デッドサイクルを開始する前に
thread.attach(false)
を実行すると新しいスレッドが作成され、Binderチャネルが確立され、すなわちサービス側とアプリケーション側の通信チャネルが作成され、Binderスレッドが作成された場合、システムプロセスと適用プロセスはBinderを通じてプロセス間通信を行うことができ、故障はなく、デッドサイクルはアプリケーションが異常に終了しないことを保証していることが理解できる.デッドサイクルが他のトランザクションを処理できるのは、デッドサイクルの前に新しいスレッドが開かれ、トランザクションの処理が新しいスレッドで完了し、トランザクションの処理がプライマリ・スレッドにフィードバックされると、Binderによってプロセス間で呼び出され、プライマリ・スレッドのHandlerによってアプリケーション・スレッド完了メッセージの処理に切り替わるためです.問2:メインラインのデッドサイクルはCPU資源を消耗しているのではないでしょうか?いやいや、ここではLinuxのpipe/epollメカニズムに関し、メインスレッドのメッセージキューにメッセージがない場合、
Queue#next()
のnativePollOnce()
メソッドにブロックされる.このとき、メインスレッドはCPUリソースを解放してスリープ状態に入る.次のメッセージがここに来るまでメインスレッドがスリープし、メインスレッドを呼び覚ます動作に保存される.この動作は、pipeパイプにデータを書き込むことでメインスレッドを呼び覚ますので、メインスレッドはメッセージがない時に睡眠を取って、大量のCPU資源を消耗しません問3:メインスレッドのメッセージはどこから来ますか.他のスレッドはHandlerを介してプライマリスレッドに送信される
二、補問
問:Androidアプリ起動プロセスは、Activity#onCreate()などのライフサイクルがLooper#loop()のデッドサイクルのために実行されないのはなぜですか.答え:Activityのライフサイクル方法はBinderのプロセス間通信によって実現され、プロセス間通信ではLooper#loop()のデッドサイクルの影響(同じスレッドではない)を受けず、システムプロセスはアプリケーションプロセスにActivityを呼び出すライフサイクル方法を通知します.まずActivity Thread内部のHandler#handleMessage()でスレッドをプライマリスレッドに切り替え、HandlerでActivityのライフサイクルメソッドの呼び出しを完了します.
三、Activityライフサイクルプロセス
プロセス実行(API 26):
:ActivityThread#main()
// Looper
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
// loop
Looper.loop();
// ,
throw new RuntimeException("Main thread loop unexpectedly exited");
:ActivityThread#attach()
// AMS
final IActivityManager mgr = ActivityManager.getService();
mgr.attachApplication(mAppThread) // Binder , AMS
AMS#attachApplicationLocked()
ActivityThread#bindApplication()
ActivityThread#sendMessage(H.BIND_APPLICATION, data) //
handleBindApplication()
// 1. Application( Application , )
// 2. appContext.setOuterContext(app), appContext Application
app = data.info.makeApplication(data.restrictedBackupMode, null);
// Application#onCreate()
mInstrumentation.callApplicationOnCreate(app);
ActivityStackSupervisor#attachApplicationLocked(app)
realStartActivityLocked()
app.thread.scheduleLaunchActivity
ActivityThread$ApplicationThread#scheduleLaunchActivity() // Binder , AMS
ActivityThread#sendMessage(H.LAUNCH_ACTIVITY, r) //
handleLaunchActivity()
// 1. Activity, LoadApk#makeApplication() Application( , )
// 2. Instrumentation#callActivityOnCreate(), Activity#onCreate()
// 3. appContext.setOuterContext(activity), appContext Activity
Activity a = performLaunchActivity(r, customIntent);
handleResumeActivity()
// ActivityClientRecord token Activity, Activity#performResume(), Instrumentation#callActivityOnResume() Activity#onResume()
performResumeActivity()
// Window (Window ? Activity#attach() ,mWindow PhoneWindow)
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
// Activity
decor.setVisibility(View.INVISIBLE);
// View
// ViewRootImpl ( )
// ViewRootImpl#checkThread() UI , UI
// ViewRootImpl , UI
wm.addView(decor, l);