android進(jìn)程通信,Android進(jìn)程管理

Android:AIDL進(jìn)程間通信基本框架

在某些業(yè)務(wù)場(chǎng)景下,我們需要在應(yīng)用中單獨(dú)開(kāi)啟一個(gè)進(jìn)程進(jìn)行一些操作。比如性能監(jiān)控,如果讓原始業(yè)務(wù)和性能監(jiān)控本身的業(yè)務(wù)跑在同一個(gè)進(jìn)程下,那么就會(huì)導(dǎo)致性能統(tǒng)計(jì)的數(shù)據(jù)的失真。

創(chuàng)新互聯(lián)長(zhǎng)期為成百上千客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開(kāi)放共贏平臺(tái),與合作伙伴共同營(yíng)造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為吉隆企業(yè)提供專業(yè)的成都網(wǎng)站建設(shè)、做網(wǎng)站,吉隆網(wǎng)站改版等技術(shù)服務(wù)。擁有10年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開(kāi)發(fā)。

而進(jìn)程間通信,一般采用AIDL機(jī)制的客戶端與服務(wù)端通信。

AIDL只能傳遞如下幾類數(shù)據(jù):

當(dāng)傳遞自定義 Parcelable 時(shí),有三處地方需要注意:

當(dāng)傳遞其他 aidl 接口時(shí),同樣必須要 import 這個(gè) aidl 文件

編寫(xiě)完 aidl 文件后,make一下工程,會(huì)在 build 下的 generated 下的 source 下的 aidl 目錄生成對(duì)應(yīng)的接口類文件。aidl 接口其實(shí)就是 API 接口,通過(guò)實(shí)現(xiàn)對(duì)應(yīng)接口類的 Stub 子類來(lái)實(shí)現(xiàn)具體的 API 邏輯;通過(guò)對(duì)應(yīng)接口類的 Stub 子類的 asInterface 方法得到具體的實(shí)現(xiàn)類,調(diào)用具體的 API 方法。

一個(gè)基本的客戶端服務(wù)端的通信結(jié)構(gòu)一般包括如下功能

客戶端的功能

服務(wù)端的功能

客戶端的相關(guān)功能實(shí)現(xiàn)比較簡(jiǎn)單,麻煩的是服務(wù)端的功能。因?yàn)?AIDL 接口定義的都是服務(wù)端的接口,是由客戶端來(lái)調(diào)用的。而想要實(shí)現(xiàn)服務(wù)端反向調(diào)用客戶端則需要通過(guò)其他手段實(shí)現(xiàn)。

想要實(shí)現(xiàn)服務(wù)端主動(dòng)連接客戶端,最好的辦法就是 服務(wù)端發(fā)送廣播,客戶端收到廣播后再主動(dòng)連接服務(wù)端 ,通過(guò)這種方式變相地實(shí)現(xiàn)服務(wù)端主動(dòng)連接客戶端的功能

想要實(shí)現(xiàn)服務(wù)端主動(dòng)斷開(kāi)客戶端,除了上面 發(fā)送廣播是一種實(shí)現(xiàn)方式外,還可以通過(guò) android 的系統(tǒng)API RemoteCallbackList,用包名作為key值來(lái)注冊(cè)遠(yuǎn)程回調(diào)接口的方式,讓服務(wù)端持有客戶端的回調(diào)接口,服務(wù)端調(diào)用回調(diào)接口,客戶端在回調(diào)接口中實(shí)現(xiàn)主動(dòng)斷開(kāi)服務(wù)端 ,通過(guò)這種方式變量地實(shí)現(xiàn)服務(wù)端主動(dòng)斷開(kāi)客戶端的功能。而采用后者會(huì)顯得更加優(yōu)雅

既然所有的操作歸根結(jié)底都是由客戶端來(lái)完成的,那么客戶端必須得有如下的功能模塊:

服務(wù)端必須得有的功能模塊:

那么,整體的通信流程就是如下的步驟:

首先是通信的 aidl 接口定義

然后是客戶端的連接操作與斷開(kāi)連接操作,包括廣播接收者的注冊(cè)以及回調(diào)接口的實(shí)現(xiàn)

然后是客戶端的拉取數(shù)據(jù)和推送數(shù)據(jù)操作

接著是服務(wù)端的 iBinder 接口的實(shí)現(xiàn),完成回調(diào)接口的注冊(cè)、業(yè)務(wù)子線程的開(kāi)啟和關(guān)閉、數(shù)據(jù)的推送和數(shù)據(jù)的拉取操作

然后是服務(wù)端的主動(dòng)連接和主動(dòng)斷開(kāi)連接操作

最后是服務(wù)端的 onUnbind 方法的實(shí)現(xiàn),對(duì)回調(diào)接口進(jìn)行反注冊(cè)

服務(wù)端模仿 FloatViewPlugin 自定義插件,實(shí)現(xiàn) IServicePlugin 接口,定制個(gè)性化的懸浮窗插件

客戶端在 Appliaction 的 onCreate方法中初始化

在 MainActivity 上實(shí)現(xiàn)連接、斷開(kāi)、數(shù)據(jù)通信

Android ParcelFileDescriptor實(shí)現(xiàn)進(jìn)程間通信

一個(gè)通信通道,實(shí)現(xiàn)跨進(jìn)程的的Socket網(wǎng)絡(luò)通信。

具體的通信通道的圖如下。

android進(jìn)程間通信是使用Binder來(lái)傳數(shù)據(jù),而B(niǎo)inder傳輸?shù)臄?shù)據(jù),有一個(gè)最為基本的要求,就是要實(shí)現(xiàn)Parcelable接口。

ParcelFileDescriptor是android提供的一個(gè)數(shù)據(jù)結(jié)構(gòu)。

ParcelFileDescriptor是可以用于進(jìn)程間Binder通信的FileDescriptor。支持stream 寫(xiě)入和stream 讀出

我們可以使用

來(lái)將PacecelFileDescriptor 與File對(duì)應(yīng)起來(lái),以實(shí)現(xiàn)進(jìn)程間的文件共享。

我們也可以使用

來(lái)建立一個(gè)pipe通信通道,ParcelFileDescriptor數(shù)組第一個(gè)元素是read端,第二個(gè)元素是write端,通過(guò)write端的AutoCloseOutputStream和read端的AutoCloseInputStream,我們就可以實(shí)現(xiàn)進(jìn)程見(jiàn)的數(shù)據(jù)流傳輸了。

發(fā)送端:

1. 業(yè)務(wù)層調(diào)用getOutputStream向通信層發(fā)起請(qǐng)求

2. 通信層通過(guò)creatPipe 建立一個(gè)ParcelFileDescriptor數(shù)組,并將write端的pipe[1]返回給業(yè)務(wù)層

3. 業(yè)務(wù)層得到pipe[1](ParcelFileDescriptor)后,可以通過(guò)AutoCloseOutputStream寫(xiě)入數(shù)據(jù)

4. 從通信層的pipe[0]的AutoCloseInputStream中讀出數(shù)據(jù)通過(guò)socket發(fā)送出去

接收端:

1. 業(yè)務(wù)層調(diào)用getInputStream向通信層發(fā)起請(qǐng)求

2. 通信層通過(guò)creatPipe 建立一個(gè)ParcelFileDescriptor數(shù)組,并將read端的pipe[0]返回給業(yè)務(wù)層

3. 業(yè)務(wù)層得到pipe 0 后,可以通過(guò)AutoCloseInputStream讀取數(shù)據(jù)。(如沒(méi)有數(shù)據(jù),則阻塞,一直等到有數(shù)據(jù)為止)

4. socket中讀取數(shù)據(jù),寫(xiě)入到通信層的pipe[1]的AutoCloseOutputStream。(pipe[1]一旦寫(xiě)入,第三步中pipe[2]就可以讀取出數(shù)據(jù))

Android跨進(jìn)程通信-共享內(nèi)存

還是先看共享內(nèi)存的使用方法,我主要介紹兩個(gè)函數(shù):

通過(guò) shmget() 函數(shù)申請(qǐng)共享內(nèi)存,它的入?yún)⑷缦?/p>

通過(guò) shmat() 函數(shù)將我們申請(qǐng)到的共享內(nèi)存映射到自己的用戶空間,映射成功會(huì)返回地址,有了這個(gè)地址,我們就可以隨意的讀寫(xiě)數(shù)據(jù)了,我們繼續(xù)看一下這個(gè)函數(shù)的入?yún)?/p>

共享內(nèi)存的原理是在內(nèi)存中單獨(dú)開(kāi)辟的一段內(nèi)存空間,這段內(nèi)存空間其實(shí)就是一個(gè)tempfs(臨時(shí)虛擬文件),tempfs是VFS的一種文件系統(tǒng),掛載在/dev/shm上,前面提到的管道pipefs也是VFS的一種文件系統(tǒng)。

由于共享的內(nèi)存空間對(duì)使用和接收進(jìn)程來(lái)講,完全無(wú)感知,就像是在自己的內(nèi)存上讀寫(xiě)數(shù)據(jù)一樣,所以也是 效率最高 的一種IPC方式。

上面提到的IPC的方式都是 在內(nèi)核空間中開(kāi)辟內(nèi)存來(lái)存儲(chǔ)數(shù)據(jù) ,寫(xiě)數(shù)據(jù)時(shí),需要將數(shù)據(jù)從用戶空間拷貝到內(nèi)核空間,讀數(shù)據(jù)時(shí),需要從內(nèi)核空間拷貝到自己的用戶空間,

共享內(nèi)存就只需要一次拷貝 ,而且共享內(nèi)存不是在內(nèi)核開(kāi)辟空間,所以可以 傳輸?shù)臄?shù)據(jù)量大 。

但是 共享內(nèi)存最大的缺點(diǎn)就是沒(méi)有并發(fā)的控制,我們一般通過(guò)信號(hào)量配合共享內(nèi)存使用,進(jìn)行同步和并發(fā)的控制 。

共享內(nèi)存在Android系統(tǒng)中主要的使用場(chǎng)景是 用來(lái)傳輸大數(shù)據(jù) ,并且 Android并沒(méi)有直接使用Linux原生的共享內(nèi)存方式,而是設(shè)計(jì)了Ashmem匿名共享內(nèi)存 。

之前說(shuō)到有名管道和匿名管道的區(qū)別在于有名管道可以在vfs目錄樹(shù)中查看到這個(gè)管道的文件,但是匿名管道不行, 所以匿名共享內(nèi)存同樣也是無(wú)法在vfs目錄中查看到 的, Android之所以要設(shè)計(jì)匿名共享內(nèi)存 ,我覺(jué)得主要是為了安全性的考慮吧。

我們來(lái)看看共享內(nèi)存的一個(gè)使用場(chǎng)景,在Android中,如果我們想要將當(dāng)前的界面顯示出來(lái),需要將當(dāng)前界面的圖元數(shù)據(jù)傳遞Surfaceflinger去做圖層混合,圖層混合之后的數(shù)據(jù)會(huì)直接送入幀緩存,送入幀緩存后,顯卡就會(huì)直接取出幀緩存里的圖元數(shù)據(jù)顯示了。

那么我們?nèi)绾螌?yīng)用的Activity的圖元數(shù)據(jù)傳遞給SurfaceFlinger呢?想要將圖像數(shù)據(jù)這樣比較大的數(shù)據(jù)跨進(jìn)程傳輸,靠binder是不行的,所以這兒便用到匿名共享內(nèi)存。

從谷歌官方提供的架構(gòu)圖可以看到,圖元數(shù)據(jù)是通過(guò)BufferQueue傳遞到SurfaceFlinger去的,當(dāng)我們想要繪制圖像的時(shí)候, 需要從BufferQueue中申請(qǐng)一個(gè)Buffer,Buffer會(huì)調(diào)用Gralloc模塊來(lái)分配共享內(nèi)存 當(dāng)作圖元緩沖區(qū)存放我們的圖元數(shù)據(jù)。

可以看到Android的匿名共享內(nèi)存是通過(guò) ashmem_create_region() 函數(shù)來(lái)申請(qǐng)共享內(nèi)存的,它會(huì)在/dev/ashmem下創(chuàng)建一個(gè)虛擬文件,Linux原生共享內(nèi)存是通過(guò)shmget()函數(shù),并會(huì)在/dev/shm下創(chuàng)建虛擬文件。

匿名共享內(nèi)存是通過(guò) mmap() 函數(shù)將申請(qǐng)到的內(nèi)存映射到自己的進(jìn)程空間,而Linux是通過(guò)*shmat()函數(shù)。

雖然函數(shù)不一樣,但是Android的匿名共享內(nèi)存和Linux的共享內(nèi)存在本質(zhì)上是大同小異的。

要使用一塊共享內(nèi)存

Android跨進(jìn)程通信

本文整理和引用他人的筆記,旨在個(gè)人復(fù)習(xí)使用。

參考鏈接:

;depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight

默認(rèn)情況下,一個(gè)app只會(huì)運(yùn)行在一個(gè)進(jìn)程中,進(jìn)程名為app的包名。

1. 分散內(nèi)存的占用

Android系統(tǒng)對(duì)每個(gè)應(yīng)用進(jìn)程的內(nèi)存占用是有限制的,占用內(nèi)存越大的進(jìn)程,被系統(tǒng)殺死的可能性就越大。使用多進(jìn)程可以減少主進(jìn)程占用的內(nèi)存,避免OOM問(wèn)題,降低被系統(tǒng)殺死的概率。

2. 實(shí)現(xiàn)多模塊

一個(gè)成熟的應(yīng)用一定是多模塊化的。項(xiàng)目解耦,模塊化,意味著開(kāi)辟新的進(jìn)程,有獨(dú)立的JVM,帶來(lái)數(shù)據(jù)解耦。模塊之間互不干預(yù),團(tuán)隊(duì)并行開(kāi)發(fā),同時(shí)責(zé)任分工也很明確。

3. 降低程序奔潰率

子進(jìn)程崩潰不會(huì)影響主進(jìn)程的運(yùn)行,能降低程序的崩潰率。

4. 實(shí)現(xiàn)一些特殊功能

比如可以實(shí)現(xiàn)推送進(jìn)程,使得主進(jìn)程退出后,能離線完成消息推送服務(wù)。還可以實(shí)現(xiàn)守護(hù)進(jìn)程,來(lái)喚醒主進(jìn)程達(dá)到?;钅康?。還可以實(shí)現(xiàn)監(jiān)控進(jìn)程專門負(fù)責(zé)上報(bào)bug,進(jìn)而提升用戶體驗(yàn)。

android:process 屬性的值以冒號(hào)開(kāi)頭的就是 私有進(jìn)程 ,否則就是 公有進(jìn)程 。當(dāng)然命名還需要符合規(guī)范,不能以數(shù)字開(kāi)頭等等。

1. 前臺(tái)進(jìn)程

2. 可見(jiàn)進(jìn)程

3. 服務(wù)進(jìn)程

4. 后臺(tái)進(jìn)程

5. 空進(jìn)程

Android 會(huì)將進(jìn)程評(píng)定為它可能達(dá)到的最高級(jí)別。另外服務(wù)于另一進(jìn)程的進(jìn)程其級(jí)別永遠(yuǎn)不會(huì)低于其所服務(wù)的進(jìn)程。

創(chuàng)建新的進(jìn)程時(shí)會(huì)創(chuàng)建新的Application對(duì)象,而我們通常在Application的onCreate方法中只是完成一些全局的初始化操作,不需要多次執(zhí)行。

解決思路:獲取當(dāng)前進(jìn)程名,判斷是否為主進(jìn)程,只有主進(jìn)程的時(shí)候才執(zhí)行初始化操作

獲取當(dāng)前進(jìn)程名的兩種方法:

Application中判斷是否是主進(jìn)程(方法1例子):

Serializable 和 Parcelable是數(shù)據(jù)序列化的兩種方式,Android中只有進(jìn)行序列化過(guò)后的對(duì)象才能通過(guò)intent和Binder傳遞。

通常序列化后的對(duì)象完成傳輸后,通過(guò)反序列化獲得的是一個(gè)新對(duì)象,而不是原來(lái)的對(duì)象。

Serializable是java接口,位于java.io的路徑下。Serializable的原理就是把Java對(duì)象序列化為二進(jìn)制文件后進(jìn)行傳遞。Serializable使用起來(lái)非常簡(jiǎn)單,只需直接實(shí)現(xiàn)該接口就可以了。

Parcelable是Google為了解決Serializable效率低下的問(wèn)題,為Android特意設(shè)計(jì)的一個(gè)接口。Parcelable的原理是將一個(gè)對(duì)象完全分解,分解成可以傳輸?shù)臄?shù)據(jù)類型(如基本數(shù)據(jù)類型)再進(jìn)行傳遞。

通常需要存到本地磁盤的數(shù)據(jù)就使用Serializable,其他情況就使用效率更高的Parcelable。

IPC 即 Inter-Process Communication (進(jìn)程間通信)。Android 基于 Linux,而 Linux 出于安全考慮,不同進(jìn)程間不能之間操作對(duì)方的數(shù)據(jù),這叫做“進(jìn)程隔離”。

每個(gè)進(jìn)程的虛擬內(nèi)存空間(進(jìn)程空間)又被分為了 用戶空間和內(nèi)核空間 , 進(jìn)程只能訪問(wèn)自身用戶空間,只有操作系統(tǒng)能訪問(wèn)內(nèi)核空間。

由于進(jìn)程只能訪問(wèn)自身用戶空間,因此在傳統(tǒng)的IPC中,發(fā)送進(jìn)程需要通過(guò)copy_from_user(系統(tǒng)調(diào)用)將數(shù)據(jù)從自身用戶空間拷貝到內(nèi)核空間,再由接受進(jìn)程通過(guò)copy_to_user從內(nèi)核空間復(fù)拷貝到自身用戶空間,共需要拷貝2次,效率十分低下。Android采用的是Binder作為IPC的機(jī)制,只需復(fù)制一次。

Binder翻譯過(guò)來(lái)是粘合劑,是進(jìn)程之間的粘合劑。

Binder IPC通信的底層原理是 通過(guò)內(nèi)存映射(mmap),將接收進(jìn)程的用戶空間映射到內(nèi)核空間 ,有了這個(gè)映射關(guān)系,接收進(jìn)程就能通過(guò)用戶空間的地址獲得內(nèi)核空間的數(shù)據(jù),這樣只需發(fā)送進(jìn)程將數(shù)據(jù)拷貝到內(nèi)核空間就可完成通訊。

一次完整的Binder IPC通信:

從IPC的角度看,Binder是一種跨進(jìn)程通信機(jī)制(一種模型),Binder 是基于 C/S 架構(gòu)的,這個(gè)通信機(jī)制中主要涉及四個(gè)角色:Client、Server、ServiceManager和Binder驅(qū)動(dòng)。

Client、Server、ServiceManager都是運(yùn)行在用戶空間的進(jìn)程,他們通過(guò)系統(tǒng)調(diào)用(open、mmap 和 ioctl)來(lái)訪問(wèn)設(shè)備文件/dev/binder,從而實(shí)現(xiàn)與Binder驅(qū)動(dòng)的交互。Binder驅(qū)動(dòng)提供進(jìn)程間通信的能力(負(fù)責(zé)完成一些底層操作,比如開(kāi)辟數(shù)據(jù)接受緩存區(qū)等),是Client、Server和ServiceManager之間的橋梁。

Client、Server就是需要進(jìn)行通信兩個(gè)的進(jìn)程,通信流程:

細(xì)心的你一定發(fā)現(xiàn)了,注冊(cè)服務(wù)和獲得服務(wù)本身就是和ServiceManager進(jìn)行跨進(jìn)程通信。其實(shí)和ServiceManager的通信的過(guò)程也是獲取Binder對(duì)象(早已創(chuàng)建在Binder驅(qū)動(dòng)中,攜帶了注冊(cè)和查詢服務(wù)等接口方法)來(lái)使用,所有需要和ServiceManager通信的進(jìn)程,只需通過(guò)0號(hào)引用,就可以獲得這個(gè)Binder對(duì)象了。

AIDL內(nèi)部原理就是基于Binder的,可以借此來(lái)分析Binder的使用。

AIDL是接口定義語(yǔ)言,簡(jiǎn)短的幾句話就能定義好一個(gè)復(fù)雜的、內(nèi)部有一定功能的java接口。

先看看ICallBack.aidl文件,這里定義了一個(gè)接口,表示了服務(wù)端提供的功能。

被定義出來(lái)的java接口繼承了IInterface接口,并且內(nèi)部提供了一個(gè)Stub抽象類給服務(wù)端(相當(dāng)于封裝了一下,服務(wù)端只需繼承這個(gè)類,然后完成功能的里面具體的實(shí)現(xiàn))。

參考:

(以下是添加了回調(diào)的最終實(shí)現(xiàn),可以看參考鏈接一步一步來(lái))

為需要使用的類,創(chuàng)建aidl文件。

系統(tǒng)會(huì)自動(dòng)在main文件下生成aidl文件夾,并在該文件夾下創(chuàng)建相應(yīng)目錄。

在java相同路徑下創(chuàng)建Student類,這里不能使用@Parcelize注解,否則會(huì)報(bào)錯(cuò)

創(chuàng)建IStudentService.aidl,定義了一個(gè)接口,該接口定義了服務(wù)端提供的功能。創(chuàng)建完后rebuild一下項(xiàng)目 (每次創(chuàng)建和修改定義接口文件都要rebuild一下)

創(chuàng)建在服務(wù)端的StudentService

可以看見(jiàn)有回調(diào),說(shuō)明客戶端也提供了接口給服務(wù)端來(lái)回調(diào)(雙向通信,此時(shí)客戶端的變成了服務(wù)端),即ICallBack.aidl

客戶端是通過(guò)Binder驅(qū)動(dòng)返回的Binder調(diào)用StudentService里的具體實(shí)現(xiàn)方法

AIDL使用注意:

Messenger可以在不同進(jìn)程中傳遞 Message 對(duì)象,在Message中放入我們需要傳遞的數(shù)據(jù),就可以輕松地實(shí)現(xiàn)數(shù)據(jù)的進(jìn)程間傳遞了。Messenger 是一種輕量級(jí)的 IPC 方案,是對(duì)AIDL的封裝,底層實(shí)現(xiàn)是 AIDL。

使用詳見(jiàn):

Android進(jìn)程間和線程間通信方式

? 進(jìn)程:是具有一定獨(dú)立功能的程序關(guān)于某個(gè)數(shù)據(jù)集合上的一次運(yùn)行活動(dòng),進(jìn)程是系統(tǒng)進(jìn)行資源分配和調(diào)度的一個(gè)獨(dú)立單位。

??線程:是進(jìn)程的一個(gè)實(shí)體,是CPU調(diào)度和分派的基本單位,它是比進(jìn)程更小的能獨(dú)立運(yùn)行的基本單位。線程自己基本上不擁有系統(tǒng)資源,只擁有一些在運(yùn)行中必不可少的資源(如程序計(jì)數(shù)器,一組寄存器和棧),但是它可與同屬一個(gè)進(jìn)程的其他的線程共享進(jìn)程所擁有的全部資源。

??區(qū)別:

??(1)、一個(gè)程序至少有一個(gè)進(jìn)程,一個(gè)進(jìn)程至少有一個(gè)線程;

??(2)、線程的劃分尺度小于進(jìn)程,使得多線程程序的并發(fā)性高;

??(3)、進(jìn)程在執(zhí)行過(guò)程中擁有獨(dú)立的內(nèi)存單元,而多個(gè)線程共享內(nèi)存,但線程之間沒(méi)有單獨(dú)的地址空間,一個(gè)線程死掉就等于整個(gè)進(jìn)程死掉。

---------------------

一、Android進(jìn)程間通信方式

1.Bundle

??由于Activity,Service,Receiver都是可以通過(guò)Intent來(lái)攜帶Bundle傳輸數(shù)據(jù)的,所以我們可以在一個(gè)進(jìn)程中通過(guò)Intent將攜帶數(shù)據(jù)的Bundle發(fā)送到另一個(gè)進(jìn)程的組件。

??缺點(diǎn):無(wú)法傳輸Bundle不支持的數(shù)據(jù)類型。

2.ContentProvider

??ContentProvider是Android四大組件之一,以表格的方式來(lái)儲(chǔ)存數(shù)據(jù),提供給外界,即Content Provider可以跨進(jìn)程訪問(wèn)其他應(yīng)用程序中的數(shù)據(jù)。用法是繼承ContentProvider,實(shí)現(xiàn)onCreate,query,update,insert,delete和getType方法,onCreate是負(fù)責(zé)創(chuàng)建時(shí)做一些初始化的工作,增刪查改的方法就是對(duì)數(shù)據(jù)的查詢和修改,getType是返回一個(gè)String,表示Uri請(qǐng)求的類型。注冊(cè)完后就可以使用ContentResolver去請(qǐng)求指定的Uri。

3.文件

??兩個(gè)進(jìn)程可以到同一個(gè)文件去交換數(shù)據(jù),我們不僅可以保存文本文件,還可以將對(duì)象持久化到文件,從另一個(gè)文件恢復(fù)。要注意的是,當(dāng)并發(fā)讀/寫(xiě)時(shí)可能會(huì)出現(xiàn)并發(fā)的問(wèn)題。

4.Broadcast

??Broadcast可以向android系統(tǒng)中所有應(yīng)用程序發(fā)送廣播,而需要跨進(jìn)程通訊的應(yīng)用程序可以監(jiān)聽(tīng)這些廣播。

5.AIDL方式

??Service和Content Provider類似,也可以訪問(wèn)其他應(yīng)用程序中的數(shù)據(jù),Content Provider返回的是Cursor對(duì)象,而Service返回的是Java對(duì)象,這種可以跨進(jìn)程通訊的服務(wù)叫AIDL服務(wù)。

? ? ?AIDL通過(guò)定義服務(wù)端暴露的接口,以提供給客戶端來(lái)調(diào)用,AIDL使服務(wù)器可以并行處理,而Messenger封裝了AIDL之后只能串行運(yùn)行,所以Messenger一般用作消息傳遞。

6.Messenger

??Messenger是基于AIDL實(shí)現(xiàn)的,服務(wù)端(被動(dòng)方)提供一個(gè)Service來(lái)處理客戶端(主動(dòng)方)連接,維護(hù)一個(gè)Handler來(lái)創(chuàng)建Messenger,在onBind時(shí)返回Messenger的binder。

??雙方用Messenger來(lái)發(fā)送數(shù)據(jù),用Handler來(lái)處理數(shù)據(jù)。Messenger處理數(shù)據(jù)依靠Handler,所以是串行的,也就是說(shuō),Handler接到多個(gè)message時(shí),就要排隊(duì)依次處理。

7.Socket

??Socket方法是通過(guò)網(wǎng)絡(luò)來(lái)進(jìn)行數(shù)據(jù)交換,注意的是要在子線程請(qǐng)求,不然會(huì)堵塞主線程??蛻舳撕头?wù)端建立連接之后即可不斷傳輸數(shù)據(jù),比較適合實(shí)時(shí)的數(shù)據(jù)傳輸

二、Android線程間通信方式

??一般說(shuō)線程間通信主要是指主線程(也叫UI線程)和子線程之間的通信,主要有以下兩種方式:

1.AsyncTask機(jī)制

??AsyncTask,異步任務(wù),也就是說(shuō)在UI線程運(yùn)行的時(shí)候,可以在后臺(tái)的執(zhí)行一些異步的操作;AsyncTask可以很容易且正確地使用UI線程,AsyncTask允許進(jìn)行后臺(tái)操作,并在不顯示使用工作線程或Handler機(jī)制的情況下,將結(jié)果反饋給UI線程。但是AsyncTask只能用于短時(shí)間的操作(最多幾秒就應(yīng)該結(jié)束的操作),如果需要長(zhǎng)時(shí)間運(yùn)行在后臺(tái),就不適合使用AsyncTask了,只能去使用Java提供的其他API來(lái)實(shí)現(xiàn)。

2.Handler機(jī)制

??Handler,繼承自O(shè)bject類,用來(lái)發(fā)送和處理Message對(duì)象或Runnable對(duì)象;Handler在創(chuàng)建時(shí)會(huì)與當(dāng)前所在的線程的Looper對(duì)象相關(guān)聯(lián)(如果當(dāng)前線程的Looper為空或不存在,則會(huì)拋出異常,此時(shí)需要在線程中主動(dòng)調(diào)用Looper.prepare()來(lái)創(chuàng)建一個(gè)Looper對(duì)象)。使用Handler的主要作用就是在后面的過(guò)程中發(fā)送和處理Message對(duì)象和讓其他的線程完成某一個(gè)動(dòng)作(如在工作線程中通過(guò)Handler對(duì)象發(fā)送一個(gè)Message對(duì)象,讓UI線程進(jìn)行UI的更新,然后UI線程就會(huì)在MessageQueue中得到這個(gè)Message對(duì)象(取出Message對(duì)象是由其相關(guān)聯(lián)的Looper對(duì)象完成的),并作出相應(yīng)的響應(yīng))。

三、Android兩個(gè)子線程之間通信

??面試的過(guò)程中,有些面試官可能會(huì)問(wèn)Android子線程之間的通信方式,由于絕大部分程序員主要關(guān)注的是Android主線程和子線程之間的通信,所以這個(gè)問(wèn)題很容易讓人懵逼。

??主線程和子線程之間的通信可以通過(guò)主線程中的handler把子線程中的message發(fā)給主線程中的looper,或者,主線程中的handler通過(guò)post向looper中發(fā)送一個(gè)runnable。但looper默認(rèn)存在于main線程中,子線程中沒(méi)有Looper,該怎么辦呢?其實(shí)原理很簡(jiǎn)單,把looper綁定到子線程中,并且創(chuàng)建一個(gè)handler。在另一個(gè)線程中通過(guò)這個(gè)handler發(fā)送消息,就可以實(shí)現(xiàn)子線程之間的通信了。

??子線程創(chuàng)建handler的兩種方式:

??方式一:給子線程創(chuàng)建Looper對(duì)象:

new Thread(new Runnable() {

? ? ? ? public void run() {?

? ? ? ? ? ? Looper.prepare();? // 給這個(gè)Thread創(chuàng)建Looper對(duì)象,一個(gè)Thead只有一個(gè)Looper對(duì)象

? ? ? ? ? ? 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,或者說(shuō)是UI線程的looper:

new Thread(new Runnable() {

? ? ? ? public void run() {?

? ? ? ? ? ? Handler handler = new Handler(Looper.getMainLooper()){ // 區(qū)別在這?。?!?

? ? ? ? ? ? ? ? @Override?

? ? ? ? ? ? ? ? public void handleMessage(Message msg) {?

? ? ? ? ? ? ? ? ? ? Toast.makeText(getApplicationContext(), "handleMessage", Toast.LENGTH_LONG).show();?

? ? ? ? ? ? ? ? }?

? ? ? ? ? ? };?

? ? ? ? ? ? handler.sendEmptyMessage(1);?

? ? ? ? };?

? ? }).start();

---------------------

本文標(biāo)題:android進(jìn)程通信,Android進(jìn)程管理
轉(zhuǎn)載來(lái)源:http://www.muchs.cn/article8/phjjop.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供靜態(tài)網(wǎng)站網(wǎng)站建設(shè)、搜索引擎優(yōu)化、、網(wǎng)站策劃用戶體驗(yàn)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

手機(jī)網(wǎng)站建設(shè)