なぜメインスレッドはLooper#loop()メソッドのデッドサイクルによって殺されなかったのか

9623 ワード

なぜメインスレッドはLooperにloop法のデッドサイクルカード死
  • 一、問題
  • 二、補問
  • 三、Activityライフサイクルフロー
  • 一、問題
    問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);