Android—ActivityThread与Handler
zygote進程
Android系統(tǒng)是基于Linux內核的,而在Linux系統(tǒng)中,所有的進程都是init進程的子孫進程,也就是說,所有的進程都是直接或者間接地由init進程fork出來的。Zygote進程也不例外,它是在系統(tǒng)啟動的過程,由init進程創(chuàng)建的。
一個Android的App進程的創(chuàng)建過程,是由 init進程 -> zygote進程 -> system_server進程 -> App進程。
zygote進程是運行app_main.cpp文件。在main函數(shù)中,會創(chuàng)建一個AppRuntime(AppRuntime是繼承于AndroidRuntime)對象,所以一個應用擁有一個虛擬機實例,然后調用它的start方法。
start方法:
- 創(chuàng)建并啟動虛擬機
- 注冊JNI服務
- 向Android虛擬機注冊Android native處理函數(shù)
- java層Zygote初始化處理
Zygote初始化:
SystemServer
SystemServer進程是Android系統(tǒng)的核心之一,大部分Android提供的服務都在該進程中,SystemServer中運行的進程公共有六十多種,介紹下重要的幾個service;
- AMS(ActivityManagerService)->ActivityManager? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ActivityManagerService是整個Android Framework框架中最為核心的一個服務,用戶應用程序的生命管理都是由它負責的。統(tǒng)籌管理著android的四大組件;統(tǒng)一調度各應用進程
- PackageManagerService -> PackageManager? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 包括對軟件包的解包,驗證,安裝以及升級等等,不能安裝.so文件的問題,應該先從這塊著手分析原因。
- WindowManagerService -> WindowManager -> PhoneWindowManager? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 和ActivityManagerService高度粘合;窗口管理,這里最核心的就是輸入事件的分發(fā)和管理。
應用啟動過程:
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所有生命周期的方法都有該類來執(zhí)行。最后mInstrumentation調用了Application的onCreate方法。
- H繼承于Handler,mH負責處理ApplicationThread發(fā)送到消息隊列的消息,Activity的生命周期都是依靠主線程的Looper.loop,當收到不同Message時則采用相應措施。
- ApplicationThread是ActivityThread的內部類,ApplicationThread內部繼承自Binder并實現(xiàn)IApplicationThread接口。Binder是C/S結構,Binder是Service,AMS是Client,ApplicationThread主要用于應用進程和AMS進程間通信,并用于AMS的調用,通過H類將消息發(fā)送到消息隊列,然后進行相應的操作。
為什么App進程做服務端呢?
仔細想想,Activity的生命周期回調是誰調用的啊。肯定不是app本身控制,而遠程服務通過監(jiān)聽到一系列的操作發(fā)起周期回調,AMS持有App的proxy,這個代理的協(xié)議是IApplicationThread,于是AMS監(jiān)控系統(tǒng)需要onResume,則通過proxy發(fā)起IApplicationThread的onResume,也就是通知服務去執(zhí)行onResume。所以這里作為Binder理解IPC,服務端就是客戶端App而不是AMS,AMS作為請求端,持有App進程的代理。
public static void main(String[] args) {//....//創(chuàng)建Looper和MessageQueue對象,用于處理主線程的消息Looper.prepareMainLooper();//創(chuàng)建ActivityThread對象ActivityThread thread = new ActivityThread(); //建立Binder通道(創(chuàng)建新線程)thread.attach(false);Looper.loop(); //消息循環(huán)運行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)的初始化:
attach()方法在調用了attachApplication()之后,經(jīng)過一系列操作,最后調用了ApplicationThread的bindApplication()方法,bindApplication中通過消息機制,sendMessage到ActivityThread,handleMessage調用了ActivityThread的handleBindApplication()。通過反射創(chuàng)建了Application對象,然后onCreate創(chuàng)建activity。
private void handleBindApplication(AppBindData data) {//創(chuàng)建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.//通過反射創(chuàng)建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發(fā)送消息,H收到消息后會將ApplicationThread中的邏輯切換到ActivityThread中去執(zhí)行,即切換到主線程中去執(zhí)行。
Handler 線程間通信
從上面我們得知Activity的生命周期都是依靠主線程的Looper.loop,主線程Handler收到不同Message時則采用相應措施。接下來介紹Handler。
Handler作用:
進行子線程與主線程之間的通信。子線程可以通過Handler來通知主線程進行UI更新。
根據(jù)Looper.loop()源碼可知里面是一個死循環(huán)在遍歷消息隊列取消息,queue.next()阻塞方法,從隊列中獲取消息。
public static void loop() {final Looper me = myLooper();......for (;;) {//獲取消息隊列中的消息Message msg = queue.next(); // might block....//然后分發(fā)消息到Handler的處理中msg.target.dispatchMessage(msg);...//釋放消息msg.recycleUnchecked();}}Android在子線程更新UI的三種方式?
new Handler(mContext.getMainLooper()).post(new Runnable() {@Overridepublic void run() {// 在這里執(zhí)行你要想的操作 比如直接在這里更新ui或者調用回調在 在回調中更新ui} });常見常用的post()類方法匯總:
- post(Runnable)
- postAtTime(Runnable,long)? ?System.currentTimeMillis() + 100000?在設定的目標時間post
- postDelayed(Runnable long)? ? 延遲多少時間再post
常見常用的send類方法匯總:
- sendEmptyMessage(int)
- sendMessage(Message)
- sendMessageAtTime(Message,long)
- sendMessageDelayed(Message,long)
Handler內部如何獲取到當前線程的Looper?
ThreadLocal。ThreadLocal可以在不同的線程中互不干擾的存儲并提供數(shù)據(jù),通過ThreadLocal可以輕松獲取每個線程的Looper。當然需要注意的是①線 程是默認沒有Looper的,如果需要使用Handler,就必須為線程創(chuàng)建Looper。我們經(jīng)常提到的主線 程,也叫UI線程,它就是ActivityThread,②ActivityThread被創(chuàng)建時就會初始化Looper,這也是在主 線程中默認可以使用Handler的原因。
系統(tǒng)為什么不允許在子線程中訪問UI?
這是因為Android的UI控件不是線程安全的,如果在多線程中并發(fā)訪問可能會導致UI控件處于不可預期的狀態(tài),那么為什么 系統(tǒng)不對UI控件的訪問加上鎖機制呢?缺點有兩個: ①首先加上鎖機制會讓UI訪問的邏輯變得復雜 ②鎖機制會降低UI訪問的效率,因為鎖機制會阻塞某些線程的執(zhí)行。 所以最簡單且高效的方法就是采用單線程模型來處理UI操作。
Looper.loop為什么不會阻塞主線程?
Activity的生命周期就是依靠Looper.loop(),Looper.loop() 不斷地接收事件、處理事件,每一個點擊觸摸或者說Activity的生命周期都是運行在 Looper.loop() 的控制之下。所以不存在主線程會被Looper.loop方法阻塞。
Handler優(yōu)化:
實現(xiàn)靜態(tài)內部類:實際項目中Handler很少采用上面匿名類的實現(xiàn)方式,因為會造成內存泄漏,大部分采用靜態(tài)內部類、建一個單類或者在onDestroy方法中removeCallbacksAndMessages。
使用HandlerThread:Loop主線程已經(jīng)有了,不需要我們自己創(chuàng)建,但是子線程默認是沒有開啟消息循環(huán)的。需要用到Looper.prepare()和Looper.loop(),當然也可以用到我們上面的實現(xiàn)方式傳回主線程,但是這樣做會增加主線程的工作量。
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、創(chuàng)建一個線程,線程名字:handler-threadmyHandlerThread = new HandlerThread( "handler-thread") ;//2、開啟一個線程myHandlerThread.start();//3、在這個線程中創(chuàng)建一個handler對象handler = new Handler( myHandlerThread.getLooper() ){@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);//這個方法是運行在 handler-thread 線程中的 ,可以執(zhí)行耗時操作Log.d( "handler " , "消息: " + msg.what + " 線程: " + Thread.currentThread().getName() ) ;}};//在主線程給handler發(fā)送消息handler.sendEmptyMessage( 1 ) ;//在子線程給handler發(fā)送數(shù)據(jù)new Thread(new Runnable() {@Overridepublic void run() {handler.sendEmptyMessage( 2 ) ;}}).start() ;}@Overrideprotected void onDestroy() {super.onDestroy();//4、釋放資源myHandlerThread.quit() ;} }因為最后執(zhí)行了quit()操作,所以內存泄漏的問題也得到解決。
總結
以上是生活随笔為你收集整理的Android—ActivityThread与Handler的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 创业者谈:畏惧失败,但也要拥抱失败
- 下一篇: 怎样洗头使头发变黑变多