日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android—ActivityThread与Handler

發布時間:2023/12/18 Android 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android—ActivityThread与Handler 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

zygote進程

Android系統是基于Linux內核的,而在Linux系統中,所有的進程都是init進程的子孫進程,也就是說,所有的進程都是直接或者間接地由init進程fork出來的。Zygote進程也不例外,它是在系統啟動的過程,由init進程創建的。

一個Android的App進程的創建過程,是由 init進程 -> zygote進程 -> system_server進程 -> App進程。

zygote進程是運行app_main.cpp文件。在main函數中,會創建一個AppRuntime(AppRuntime是繼承于AndroidRuntime)對象,所以一個應用擁有一個虛擬機實例,然后調用它的start方法。

start方法:

  • 創建并啟動虛擬機
  • 注冊JNI服務
  • 向Android虛擬機注冊Android native處理函數
  • java層Zygote初始化處理

Zygote初始化:

  • 調用registerZygoteSocket()注冊套接字,用來和ActivityManagerServer通訊,接收新的Android應用程序運行請求。? ? ? ? ? ? 創建LocalServerSocket實例(本地Socket服務端)接收生成新Android進程的信息,一個應用進程通過Binder請求SystemServer進程,SystemServer進程發送socket消息給Zygote進程。
  • 調用preloadClasses()和preloadResource()來加載應用Framework使用的類與資源。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Zygote對公共類與資源進行預加載,當應用程序啟動時只需要加載自身特有的類與資源就行了,提高了應用軟件的啟動速度。
  • 調用startSystemServer()運行SystemServer進程,來啟動各種服務。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? PackageManagerService和ActivityManagerService, 都是由SystemServer進程啟動。
  • 調用runSelectLoopMode()來循環監聽,進入一個無限循環,socket接口等待ActivityManagerService請求創建新的進程。
  • 每個應用都會持有一個ART實例。
  • SystemServer

    SystemServer進程是Android系統的核心之一,大部分Android提供的服務都在該進程中,SystemServer中運行的進程公共有六十多種,介紹下重要的幾個service;

    • AMS(ActivityManagerService)->ActivityManager? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ActivityManagerService是整個Android Framework框架中最為核心的一個服務,用戶應用程序的生命管理都是由它負責的。統籌管理著android的四大組件;統一調度各應用進程
    • PackageManagerService -> PackageManager? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 包括對軟件包的解包,驗證,安裝以及升級等等,不能安裝.so文件的問題,應該先從這塊著手分析原因。
    • WindowManagerService -> WindowManager -> PhoneWindowManager? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 和ActivityManagerService高度粘合;窗口管理,這里最核心的就是輸入事件的分發和管理。

    應用啟動過程:

    ActivityThread

    ActivityThread就是主線程或UI線程,ActivityThread的main方法是整個APP的入口。

    public final class ActivityThread {//... final H mH = new H();final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();final ApplicationThread mAppThread = new ApplicationThread();  private class ApplicationThread extends ApplicationThreadNative {    //... }private class H extends Handler {//...}//...}

    Activity信息全部被存儲在ActivityThread的成員變量mActivities中。mServices則保存了所有service的信息。

    final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();

    ActivityThread有三個重要的類,Instrumentation、H和ApplicationThread

    • mInstrumentation是Instrumentation類的對象,Instrumentation類為ActivityThread的一個工具類,在ActivityThread中初始化,一個進程只存在一個Instrumentation對象,在每個Activity初始化時,會通過Activity的Attach方法,將該引用傳遞給Activity。Activity所有生命周期的方法都有該類來執行。最后mInstrumentation調用了Application的onCreate方法。
    • H繼承于Handler,mH負責處理ApplicationThread發送到消息隊列的消息,Activity的生命周期都是依靠主線程的Looper.loop,當收到不同Message時則采用相應措施。
    • ApplicationThread是ActivityThread的內部類,ApplicationThread內部繼承自Binder并實現IApplicationThread接口。Binder是C/S結構,Binder是Service,AMS是Client,ApplicationThread主要用于應用進程和AMS進程間通信,并用于AMS的調用,通過H類將消息發送到消息隊列,然后進行相應的操作。

    為什么App進程做服務端呢?

    仔細想想,Activity的生命周期回調是誰調用的啊。肯定不是app本身控制,而遠程服務通過監聽到一系列的操作發起周期回調,AMS持有App的proxy,這個代理的協議是IApplicationThread,于是AMS監控系統需要onResume,則通過proxy發起IApplicationThread的onResume,也就是通知服務去執行onResume。所以這里作為Binder理解IPC,服務端就是客戶端App而不是AMS,AMS作為請求端,持有App進程的代理。

    public static void main(String[] args) {//....//創建Looper和MessageQueue對象,用于處理主線程的消息Looper.prepareMainLooper();//創建ActivityThread對象ActivityThread thread = new ActivityThread(); //建立Binder通道(創建新線程)thread.attach(false);Looper.loop(); //消息循環運行throw new RuntimeException("Main thread loop unexpectedly exited");} private void attach(boolean system){...final IActivityManager mgr = ActivityManager.getService();try {//將ApplicationThread這個Binder交給了ActivityManagerServicemgr.attachApplication(mAppThread);} catch (RemoteException ex) {throw ex.rethrowFromSystemServer();}...BinderInternal.addGcWatcher(new Runnable() {@Override public void run() {if (!mSomeActivitiesChanged) {return;}Runtime runtime = Runtime.getRuntime();long dalvikMax = runtime.maxMemory();long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();if (dalvikUsed > ((3*dalvikMax)/4)) {if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)+ " total=" + (runtime.totalMemory()/1024)+ " used=" + (dalvikUsed/1024));mSomeActivitiesChanged = false;try {mgr.releaseSomeActivities(mAppThread);} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}}});... }

    主線程(ActivityThread)的初始化:

  • 開啟消息循環。調用Looper.prepareLoop() Looper.loop(),開啟主線程的消息循環,以便于ApplicationThread調用ActivityThread中的生命周期方法。
  • 通知ActivityManagerService。調用ActivityThread.attach()方法,attach()方法在調用了attachApplication()將ApplicationThread這個Binder交給了ActivityManagerService,意味著ActivityManagerService可以通過ApplicationThread控制我們的應用,建立了服務器端對客戶端的通信渠道。
  • 添加GCWatcher。在attach()方法中,添加了監聽dialvik內存使用情況得監聽者GcWatcher,當內存使用超過總容量的3/4,則打印Log進行記錄,并且調用ActivityManagerService的releaseSomeActivities()進行內存釋放操作,以防止內存溢出導致應用崩潰。
  • attach()方法在調用了attachApplication()之后,經過一系列操作,最后調用了ApplicationThread的bindApplication()方法,bindApplication中通過消息機制,sendMessage到ActivityThread,handleMessage調用了ActivityThread的handleBindApplication()。通過反射創建了Application對象,然后onCreate創建activity。

    private void handleBindApplication(AppBindData data) {//創建appContext final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);try {// If the app is being launched for full backup or restore, bring it up in// a restricted environment with the base application class.//通過反射創建Applicationapp = data.info.makeApplication(data.restrictedBackupMode, null);mInitialApplication = app;try {//調用Application的onCreate方法mInstrumentation.callApplicationOnCreate(app);} catch (Exception e) {}} }public void callApplicationOnCreate(Application app) {app.onCreate();}

    總結:ActivityThread通過ApplicationThread和AMS進行進程間通訊,AMS接受 ActivityThread的請求后會回調ApplicationThread中的Binder方法,然后ApplicationThread會向H發送消息,H收到消息后會將ApplicationThread中的邏輯切換到ActivityThread中去執行,即切換到主線程中去執行。

    Handler 線程間通信

    從上面我們得知Activity的生命周期都是依靠主線程的Looper.loop,主線程Handler收到不同Message時則采用相應措施。接下來介紹Handler。

    Handler作用:

    進行子線程與主線程之間的通信。子線程可以通過Handler來通知主線程進行UI更新。

    根據Looper.loop()源碼可知里面是一個死循環在遍歷消息隊列取消息,queue.next()阻塞方法,從隊列中獲取消息。

    public static void loop() {final Looper me = myLooper();......for (;;) {//獲取消息隊列中的消息Message msg = queue.next(); // might block....//然后分發消息到Handler的處理中msg.target.dispatchMessage(msg);...//釋放消息msg.recycleUnchecked();}}

    Android在子線程更新UI的三種方式?

    new Handler(mContext.getMainLooper()).post(new Runnable() {@Overridepublic void run() {// 在這里執行你要想的操作 比如直接在這里更新ui或者調用回調在 在回調中更新ui} });

    常見常用的post()類方法匯總:

    • post(Runnable)
    • postAtTime(Runnable,long)? ?System.currentTimeMillis() + 100000?在設定的目標時間post
    • postDelayed(Runnable long)? ? 延遲多少時間再post
    ((Activity) context).runOnUiThread(new Runnable() {@Overridepublic void run() {// 在這里執行你要想的操作 比如直接在這里更新ui或者調用回調在 在回調中更新ui} }); private Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);switch (msg.what) {case ACTIVENUMBER:MaintainProtos.ActiveNumber activeNumber = (MaintainProtos.ActiveNumber) msg.obj;break;}} };Message msg = Message.obtain();msg.what = ACTIVENUMBER;msg.obj = activeNumber;mHandler.sendMessage(msg);

    常見常用的send類方法匯總:

    • sendEmptyMessage(int)
    • sendMessage(Message)
    • sendMessageAtTime(Message,long)
    • sendMessageDelayed(Message,long)

    Handler內部如何獲取到當前線程的Looper?

    ThreadLocal。ThreadLocal可以在不同的線程中互不干擾的存儲并提供數據,通過ThreadLocal可以輕松獲取每個線程的Looper。當然需要注意的是①線 程是默認沒有Looper的,如果需要使用Handler,就必須為線程創建Looper。我們經常提到的主線 程,也叫UI線程,它就是ActivityThread,②ActivityThread被創建時就會初始化Looper,這也是在主 線程中默認可以使用Handler的原因。

    系統為什么不允許在子線程中訪問UI?

    這是因為Android的UI控件不是線程安全的,如果在多線程中并發訪問可能會導致UI控件處于不可預期的狀態,那么為什么 系統不對UI控件的訪問加上鎖機制呢?缺點有兩個: ①首先加上鎖機制會讓UI訪問的邏輯變得復雜 ②鎖機制會降低UI訪問的效率,因為鎖機制會阻塞某些線程的執行。 所以最簡單且高效的方法就是采用單線程模型來處理UI操作。

    Looper.loop為什么不會阻塞主線程?

    Activity的生命周期就是依靠Looper.loop(),Looper.loop() 不斷地接收事件、處理事件,每一個點擊觸摸或者說Activity的生命周期都是運行在 Looper.loop() 的控制之下。所以不存在主線程會被Looper.loop方法阻塞。

    Handler優化:

    實現靜態內部類:實際項目中Handler很少采用上面匿名類的實現方式,因為會造成內存泄漏,大部分采用靜態內部類、建一個單類或者在onDestroy方法中removeCallbacksAndMessages。

    使用HandlerThread:Loop主線程已經有了,不需要我們自己創建,但是子線程默認是沒有開啟消息循環的。需要用到Looper.prepare()和Looper.loop(),當然也可以用到我們上面的實現方式傳回主線程,但是這樣做會增加主線程的工作量。

    HandlerThread:本質上就是一個普通Thread,只不過內部建立了Looper。

    public class MainActivity extends AppCompatActivity {private HandlerThread myHandlerThread ;private Handler handler ;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//1、創建一個線程,線程名字:handler-threadmyHandlerThread = new HandlerThread( "handler-thread") ;//2、開啟一個線程myHandlerThread.start();//3、在這個線程中創建一個handler對象handler = new Handler( myHandlerThread.getLooper() ){@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);//這個方法是運行在 handler-thread 線程中的 ,可以執行耗時操作Log.d( "handler " , "消息: " + msg.what + " 線程: " + Thread.currentThread().getName() ) ;}};//在主線程給handler發送消息handler.sendEmptyMessage( 1 ) ;//在子線程給handler發送數據new Thread(new Runnable() {@Overridepublic void run() {handler.sendEmptyMessage( 2 ) ;}}).start() ;}@Overrideprotected void onDestroy() {super.onDestroy();//4、釋放資源myHandlerThread.quit() ;} }

    因為最后執行了quit()操作,所以內存泄漏的問題也得到解決。

    總結

    以上是生活随笔為你收集整理的Android—ActivityThread与Handler的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。