---------------------
壹、Android進程間通信方式
1.Bundle
由於Activity,Service,Receiver都是可以通過Intent來攜帶Bundle傳輸數據的,所以我們可以在壹個進程中通過Intent將攜帶數據的Bundle發送到另壹個進程的組件。 缺點:無法傳輸Bundle不支持的數據類型。2.ContentProvider
ContentProvider是Android四大組件之壹,以表格的方式來儲存數據,提供給外界,即Content Provider可以跨進程訪問其他應用程序中的數據。用法是繼承ContentProvider,實現onCreate,query,update,insert,delete和getType方法,onCreate是負責創建時做壹些初始化的工作,增刪查改的方法就是對數據的查詢和修改,getType是返回壹個String,表示Uri請求的類型。註冊完後就可以使用ContentResolver去請求指定的Uri。3.文件
兩個進程可以到同壹個文件去交換數據,我們不僅可以保存文本文件,還可以將對象持久化到文件,從另壹個文件恢復。要註意的是,當並發讀/寫時可能會出現並發的問題。4.Broadcast
Broadcast可以向android系統中所有應用程序發送廣播,而需要跨進程通訊的應用程序可以監聽這些廣播。5.AIDL方式
Service和Content Provider類似,也可以訪問其他應用程序中的數據,Content Provider返回的是Cursor對象,而Service返回的是Java對象,這種可以跨進程通訊的服務叫AIDL服務。AIDL通過定義服務端暴露的接口,以提供給客戶端來調用,AIDL使服務器可以並行處理,而Messenger封裝了AIDL之後只能串行運行,所以Messenger壹般用作消息傳遞。
6.Messenger
Messenger是基於AIDL實現的,服務端(被動方)提供壹個Service來處理客戶端(主動方)連接,維護壹個Handler來創建Messenger,在onBind時返回Messenger的binder。 雙方用Messenger來發送數據,用Handler來處理數據。Messenger處理數據依靠Handler,所以是串行的,也就是說,Handler接到多個message時,就要排隊依次處理。7.Socket
Socket方法是通過網絡來進行數據交換,註意的是要在子線程請求,不然會堵塞主線程。客戶端和服務端建立連接之後即可不斷傳輸數據,比較適合實時的數據傳輸二、Android線程間通信方式
壹般說線程間通信主要是指主線程(也叫UI線程)和子線程之間的通信,主要有以下兩種方式:1.AsyncTask機制
AsyncTask,異步任務,也就是說在UI線程運行的時候,可以在後臺的執行壹些異步的操作;AsyncTask可以很容易且正確地使用UI線程,AsyncTask允許進行後臺操作,並在不顯示使用工作線程或Handler機制的情況下,將結果反饋給UI線程。但是AsyncTask只能用於短時間的操作(最多幾秒就應該結束的操作),如果需要長時間運行在後臺,就不適合使用AsyncTask了,只能去使用Java提供的其他API來實現。2.Handler機制
Handler,繼承自Object類,用來發送和處理Message對象或Runnable對象;Handler在創建時會與當前所在的線程的Looper對象相關聯(如果當前線程的Looper為空或不存在,則會拋出異常,此時需要在線程中主動調用Looper.prepare()來創建壹個Looper對象)。使用Handler的主要作用就是在後面的過程中發送和處理Message對象和讓其他的線程完成某壹個動作(如在工作線程中通過Handler對象發送壹個Message對象,讓UI線程進行UI的更新,然後UI線程就會在MessageQueue中得到這個Message對象(取出Message對象是由其相關聯的Looper對象完成的),並作出相應的響應)。三、Android兩個子線程之間通信
面試的過程中,有些面試官可能會問Android子線程之間的通信方式,由於絕大部分程序員主要關註的是Android主線程和子線程之間的通信,所以這個問題很容易讓人懵逼。 主線程和子線程之間的通信可以通過主線程中的handler把子線程中的message發給主線程中的looper,或者,主線程中的handler通過post向looper中發送壹個runnable。但looper默認存在於main線程中,子線程中沒有Looper,該怎麽辦呢?其實原理很簡單,把looper綁定到子線程中,並且創建壹個handler。在另壹個線程中通過這個handler發送消息,就可以實現子線程之間的通信了。 子線程創建handler的兩種方式: 方式壹:給子線程創建Looper對象:new Thread(new Runnable() {
public void run() {
Looper.prepare(); // 給這個Thread創建Looper對象,壹個Thead只有壹個Looper對象
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
Toast.makeText(getApplicationContext(), "handleMessage", Toast.LENGTH_LONG).show();
}
};
handler.sendEmptyMessage(1);
Looper.loop(); // 不斷遍歷MessageQueue中是否有消息
};
}).start();
---------------------
方式二:獲取主線程的looper,或者說是UI線程的looper:
new Thread(new Runnable() {
public void run() {
Handler handler = new Handler(Looper.getMainLooper()){ // 區別在這!!!
@Override
public void handleMessage(Message msg) {
Toast.makeText(getApplicationContext(), "handleMessage", Toast.LENGTH_LONG).show();
}
};
handler.sendEmptyMessage(1);
};
}).start();