成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Android IPC機(jī)制理解

duan199226 / 2176人閱讀

摘要:什么是機(jī)制機(jī)制,含義為進(jìn)程間通信或者跨進(jìn)程通信,是指兩個(gè)進(jìn)程之間進(jìn)行數(shù)據(jù)交換的過(guò)程。線程同步機(jī)制完全失效。五使用是中提供的專門用于不同應(yīng)用間進(jìn)行數(shù)據(jù)共享的方式,從這一點(diǎn)來(lái)看,它天生就適合進(jìn)程間通信。

什么是IPC機(jī)制?

IPC機(jī)制,含義為進(jìn)程間通信或者跨進(jìn)程通信,是指兩個(gè)進(jìn)程之間進(jìn)行數(shù)據(jù)交換的過(guò)程。

任何一個(gè)操作系統(tǒng),線程是CPU可以操作的最小單元,同時(shí)線程是一種有限的系統(tǒng)資源。而進(jìn)程一般指一個(gè)執(zhí)行單元,在PC和移動(dòng)設(shè)備上指一個(gè)程序或者一個(gè)應(yīng)用。一個(gè)進(jìn)程可以包含多個(gè)線程,因此進(jìn)程和線程是包含與被包含的關(guān)系。

Android多進(jìn)程模式

正常情況下,在Android中多進(jìn)程是指一個(gè)應(yīng)用中存在多個(gè)進(jìn)程的情況,因此這里不討論兩個(gè)應(yīng)用之間的多進(jìn)程情況。首先,在Android中使用多進(jìn)程只有一種方法,那就是給四大組件(Activity、Service、Receiver、ContentProvider)在AndroidMenifest中指定android:process屬性,除此之外沒(méi)有其他辦法,也就是說(shuō)我們無(wú)法給一個(gè)線程或者一個(gè)實(shí)體類指定其運(yùn)行時(shí)所在的進(jìn)程。其實(shí)還有另一種非常規(guī)的多進(jìn)程方法,那就是通過(guò)JNI在native層去fork一個(gè)新的進(jìn)程,但是這種方法屬于特殊情況,也不是常用的創(chuàng)建多進(jìn)程的方式,因此我們暫時(shí)不考慮這種方式。


????????
????????????????
????????????????
????????
????
????

上述代碼中就出現(xiàn)了三個(gè)進(jìn)程,上面的示例分別為SecondActivity和ThirdActivity指定了process屬性,并且它們的屬性值不同,這意味著當(dāng)前應(yīng)用又增加了兩個(gè)新進(jìn)程。

假設(shè)當(dāng)前應(yīng)用的包名為“com.ryg.chapter_2”,

當(dāng)SecondActivity啟動(dòng)時(shí),系統(tǒng)會(huì)為它創(chuàng)建一個(gè)多帶帶的進(jìn)程,進(jìn)程名為“com.ryg.chapter_2:remote”;

當(dāng)ThirdActivity啟動(dòng)時(shí),系統(tǒng)也會(huì)為它創(chuàng)建一個(gè)多帶帶的進(jìn)程,進(jìn)程名為“com.ryg.chapter_2.remote”。

同時(shí)入口Activity是MainActivity,沒(méi)有為它指定process屬性,那么它運(yùn)行在默認(rèn)進(jìn)程中,默認(rèn)進(jìn)程的進(jìn)程名是包名。

但是,實(shí)際使用中多進(jìn)程是有很多問(wèn)題需要處理的,例如以下問(wèn)題:

(1)靜態(tài)成員和單例模式完全失效。

(2)線程同步機(jī)制完全失效。

(3)SharedPreferences的可靠性下降。

(4)Application會(huì)多次創(chuàng)建。

簡(jiǎn)單來(lái)說(shuō),第(1),(2)問(wèn)題都是因?yàn)槎噙M(jìn)程的內(nèi)存塊不同,所以數(shù)據(jù)共享也會(huì)出現(xiàn)問(wèn)題;第三個(gè)是因?yàn)槌霈F(xiàn)多進(jìn)程,那么對(duì)SharedPreferences同時(shí)讀寫,會(huì)出現(xiàn)

數(shù)據(jù)不同步的安全問(wèn)題;第(4),每一次開(kāi)啟多進(jìn)程,相當(dāng)于重啟了一個(gè)應(yīng)用程序,所以application一定會(huì)重走一次。

IPC機(jī)制實(shí)現(xiàn)的基礎(chǔ) 一、Serializable接口

首先,Serializable接口是一個(gè)空接口,作用是用來(lái)處理序列化的,為對(duì)象提供標(biāo)準(zhǔn)的序列化和反序列化操作。

讓一個(gè)對(duì)象實(shí)現(xiàn)序列化,只需要這個(gè)類實(shí)現(xiàn)Serializable接口并聲明一個(gè)serialVersionUID即可,實(shí)際上,甚至這個(gè)serialVersionUID也不是必需的,我們不聲明這個(gè)serialVersionUID同樣也可以實(shí)現(xiàn)序列化,但是會(huì)對(duì)反序列化造成一定不確定因素。

例如:

public?class?User?implements?Serializable?{
?????????private?static?final?long?serialVersionUID?=?519067123721295773L;
?????????public?int?userId;
?????????public?String?userName;
?????????public?boolean?isMale;
????????...
????}

實(shí)際上,進(jìn)行對(duì)象的序列化和反序列化也非常簡(jiǎn)單,只需要采用ObjectOutputStream和ObjectInputStream即可輕松實(shí)現(xiàn):

//序列化過(guò)程
????User?user?=?new?User(0,"jake",true);
????ObjectOutputStream?out?=?new?ObjectOutputStream(
????????????????new?FileOutputStream("cache.txt"));
????out.writeObject(user);
????out.close();
????//反序列化過(guò)程
????ObjectInputStream?in?=?new?ObjectInputStream(
????????????????new?FileInputStream("cache.txt"));
????User?newUser?=?(User)?in.readObject();
????in.close();

所謂的序列化,就是把實(shí)現(xiàn)了Serializable接口的User對(duì)象寫到文件中就可以快速恢復(fù)了,恢復(fù)后的對(duì)象newUser和user的內(nèi)容完全一樣,但是兩者并不是同一個(gè)對(duì)象。

那么現(xiàn)在,serialVersionUID的作用就體現(xiàn)出來(lái)了,這個(gè)serialVersionUID是用來(lái)輔助序列化和反序列化過(guò)程的,原則上序列化后的數(shù)據(jù)中的serialVersionUID只有和當(dāng)前類的serialVersionUID相同才能夠正常地被反序列化。

serialVersionUID的詳細(xì)工作機(jī)制是這樣的:序列化的時(shí)候系統(tǒng)會(huì)把當(dāng)前類的serialVersionUID寫入序列化的文件中(也可能是其他中介),當(dāng)反序列化的時(shí)候系統(tǒng)會(huì)去檢測(cè)文件中的serialVersionUID,看它是否和當(dāng)前類的serialVersionUID一致,如果一致就說(shuō)明序列化的類的版本和當(dāng)前類的版本是相同的,這個(gè)時(shí)候可以成功反序列化;否則就說(shuō)明當(dāng)前類和序列化的類相比發(fā)生了某些變換,比如成員變量的數(shù)量、類型可能發(fā)生了改變,這個(gè)時(shí)候是無(wú)法正常反序列化的。

二、Parcelable接口

Parcelable也是一個(gè)接口,只要實(shí)現(xiàn)這個(gè)接口,一個(gè)類的對(duì)象就可以實(shí)現(xiàn)序列化并可以通過(guò)Intent和Binder傳遞。

public?class?User?implements?Parcelable?{
?????????public?int?userId;
?????????public?String?userName;
?????????public?boolean?isMale;
?????????public?Book?book;
?????????public?User(int?userId,String?userName,boolean?isMale)?{
?????????????this.userId?=?userId;
?????????????this.userName?=?userName;
?????????????this.isMale?=?isMale;
?????????}
?????????public?int?describeContents()?{
?????????????return?0;
?????????}
?????????public?void?writeToParcel(Parcel?out,int?flags)?{
?????????????out.writeInt(userId);
?????????????out.writeString(userName);
?????????????out.writeInt(isMale???1?:?0);
?????????????out.writeParcelable(book,0);
?????????}
?????????public?static?final?Parcelable.Creator?CREATOR?=?new?Parcelable.
?????????Creator()?{
?????????????public?User?createFromParcel(Parcel?in)?{
?????????????????return?new?User(in);
?????????????}
?????????????public?User[]?newArray(int?size)?{
?????????????????return?new?User[size];
?????????????}
?????????};
?????????private?User(Parcel?in)?{
?????????????userId?=?in.readInt();
?????????????userName?=?in.readString();
?????????????isMale?=?in.readInt()?==?1;
?????????????book?=?in.readParcelable(Thread.currentThread().getContextClass-
?????????????Loader());
?????????}
????}
????????

這里先說(shuō)一下Parcel,Parcel內(nèi)部包裝了可序列化的數(shù)據(jù),可以在Binder中自由傳輸。從上述代碼中可以看出,在序列化過(guò)程中需要實(shí)現(xiàn)的功能有序列化、反序列化和內(nèi)容描述。

序列化功能由writeToParcel方法來(lái)完成,最終是通過(guò)Parcel中的一系列write方法來(lái)完成的;

反序列化功能由CREATOR來(lái)完成,其內(nèi)部標(biāo)明了如何創(chuàng)建序列化對(duì)象和數(shù)組,并通過(guò)Parcel的一系列read方法來(lái)完成反序列化過(guò)程;

內(nèi)容描述功能由describeContents方法來(lái)完成,幾乎在所有情況下這個(gè)方法都應(yīng)該返回0,僅當(dāng)當(dāng)前對(duì)象中存在文件描述符時(shí),此方法返回1。

Parcelable和Serializable和區(qū)別

Serializable是Java中的序列化接口,其使用起來(lái)簡(jiǎn)單但是開(kāi)銷很大,序列化和反序列化過(guò)程需要大量I/O操作。而Parcelable是Android中的序列化方式,因此更適合用在Android平臺(tái)上,它的缺點(diǎn)就是使用起來(lái)稍微麻煩點(diǎn),但是它的效率很高,這是Android推薦的序列化方式,因此我們要首選Parcelable。Parcelable主要用在內(nèi)存序列化上,通過(guò)Parcelable將對(duì)象序列化到存儲(chǔ)設(shè)備中或者將對(duì)象序列化后通過(guò)網(wǎng)絡(luò)傳輸也都是可以的,但是這個(gè)過(guò)程會(huì)稍顯復(fù)雜,因此在這兩種情況下建議大家使用Serializable。

Android中的IPC方式 一、使用Bundle

四大組件中的三大組件(Activity、Service、Receiver)都是支持在Intent中傳遞Bundle數(shù)據(jù)的,由于Bundle實(shí)現(xiàn)了Parcelable接口,所以它可以方便地在不同的進(jìn)程間傳輸?;谶@一點(diǎn),當(dāng)我們?cè)谝粋€(gè)進(jìn)程中啟動(dòng)了另一個(gè)進(jìn)程的Activity、Service和Receiver,我們就可以在Bundle中附加我們需要傳輸給遠(yuǎn)程進(jìn)程的信息并通過(guò)Intent發(fā)送出去。當(dāng)然,我們傳輸?shù)臄?shù)據(jù)必須能夠被序列化,比如基本類型、實(shí)現(xiàn)了Parcellable接口的對(duì)象、實(shí)現(xiàn)了Serializable接口的對(duì)象以及一些Android支持的特殊對(duì)象

二、使用文件共享

共享文件也是一種不錯(cuò)的進(jìn)程間通信方式,兩個(gè)進(jìn)程通過(guò)讀/寫同一個(gè)文件來(lái)交換數(shù)據(jù),比如A進(jìn)程把數(shù)據(jù)寫入文件,B進(jìn)程通過(guò)讀取這個(gè)文件來(lái)獲取數(shù)據(jù)。

但是,我們知道,通過(guò)文件共享這種方式來(lái)共享數(shù)據(jù)對(duì)文件格式是沒(méi)有具體要求的,比如可以是文本文件,也可以是XML文件,只要讀/寫雙方約定數(shù)據(jù)格式即可。通過(guò)文件共享的方式也是有局限性的,比如并發(fā)讀/寫的問(wèn)題。

當(dāng)然,SharedPreferences是個(gè)特例,眾所周知,SharedPreferences是Android中提供的輕量級(jí)存儲(chǔ)方案,它通過(guò)鍵值對(duì)的方式來(lái)存儲(chǔ)數(shù)據(jù),在底層實(shí)現(xiàn)上它采用XML文件來(lái)存儲(chǔ)鍵值對(duì),每個(gè)應(yīng)用的SharedPreferences文件都可以在當(dāng)前包所在的data目錄下查看到。一般來(lái)說(shuō),它的目錄位于/data/data/package name/shared_prefs目錄下,其中package name表示的是當(dāng)前應(yīng)用的包名。從本質(zhì)上來(lái)說(shuō),SharedPreferences也屬于文件的一種,但是由于系統(tǒng)對(duì)它的讀/寫有一定的緩存策略,即在內(nèi)存中會(huì)有一份SharedPreferences文件的緩存,因此在多進(jìn)程模式下,系統(tǒng)對(duì)它的讀/寫就變得不可靠,當(dāng)面對(duì)高并發(fā)的讀/寫訪問(wèn),Sharedpreferences有很大幾率會(huì)丟失數(shù)據(jù),因此,不建議在進(jìn)程間通信中使用SharedPreferences。

三、使用Messenger

Messenger是一種輕量級(jí)的IPC方案,它的底層實(shí)現(xiàn)是AIDL。

注意:這里的Messenger,不同于handler,handler是無(wú)法在進(jìn)程間通信的。

實(shí)現(xiàn)一個(gè)Messenger有如下幾個(gè)步驟,分為服務(wù)端和客戶端。

服務(wù)端

我們需要在服務(wù)端創(chuàng)建一個(gè)Service來(lái)處理客戶端的連接請(qǐng)求,同時(shí)創(chuàng)建一個(gè)Handler并通過(guò)它來(lái)創(chuàng)建一個(gè)Messenger對(duì)象,然后在Service的onBind中返回這個(gè)Messenger對(duì)象底層的Binder即可。

public?class?MessengerActivity?extends?Activity?{
?????????private?static?final?String?TAG?=?"?MessengerActivity";
?????????private?Messenger?mService;
?????????private?ServiceConnection?mConnection?=?new?ServiceConnection()?{
?????????????public?void?onServiceConnected(ComponentName?className,IBinder
?????????????service)?{
?????????????????mService?=?new?Messenger(service);
?????????????????Message?msg?=?Message.obtain(null,MyConstants.MSG_FROM_CLIENT);
?????????????????Bundle?data?=?new?Bundle();
?????????????????data.putString("msg","hello,this?is?client.");
?????????????????msg.setData(data);
?????????????????try?{
?????????????????????mService.send(msg);
?????????????????}?catch?(RemoteException?e)?{
?????????????????????e.printStackTrace();
?????????????????}
?????????????}
?????????????public?void?onServiceDisconnected(ComponentName?className)?{
?????????????}
?????????};
?????????@Override
?????????protected?void?onCreate(Bundle?savedInstanceState)?{
?????????????super.onCreate(savedInstanceState);
?????????????setContentView(R.layout.activity_messenger);
?????????????Intent?intent?=?new?Intent(this,MessengerService.class);
?????????????bindService(intent,mConnection,Context.BIND_AUTO_CREATE);
?????????}
?????????@Override
?????????protected?void?onDestroy()?{
?????????????unbindService(mConnection);
?????????????super.onDestroy();
?????????}
????}

客戶端

客戶端進(jìn)程中,首先要綁定服務(wù)端的Service,綁定成功后用服務(wù)端返回的IBinder對(duì)象創(chuàng)建一個(gè)Messenger,通過(guò)這個(gè)Messenger就可以向服務(wù)端發(fā)送消息了,發(fā)消息類型為Message對(duì)象。
如果需要服務(wù)端能夠回應(yīng)客戶端,就和服務(wù)端一樣,我們還需要?jiǎng)?chuàng)建一個(gè)Handler并創(chuàng)建一個(gè)新的Messenger,并把這個(gè)Messenger對(duì)象通過(guò)Message的replyTo參數(shù)傳遞給服務(wù)端,服務(wù)端通過(guò)這個(gè)replyTo參數(shù)就可以回應(yīng)客戶端。

public?class?MessengerActivity?extends?Activity?{
?????????private?static?final?String?TAG?=?"?MessengerActivity";
?????????private?Messenger?mService;
?????????private?ServiceConnection?mConnection?=?new?ServiceConnection()?{
?????????????public?void?onServiceConnected(ComponentName?className,IBinder
?????????????service)?{
?????????????????mService?=?new?Messenger(service);
?????????????????Message?msg?=?Message.obtain(null,MyConstants.MSG_FROM_CLIENT);
?????????????????Bundle?data?=?new?Bundle();
?????????????????data.putString("msg","hello,this?is?client.");
?????????????????msg.setData(data);
?????????????????try?{
?????????????????????mService.send(msg);
?????????????????}?catch?(RemoteException?e)?{
?????????????????????e.printStackTrace();
?????????????????}
?????????????}
?????????????public?void?onServiceDisconnected(ComponentName?className)?{
?????????????}
?????????};
?????????@Override
?????????protected?void?onCreate(Bundle?savedInstanceState)?{
?????????????super.onCreate(savedInstanceState);
?????????????setContentView(R.layout.activity_messenger);
?????????????Intent?intent?=?new?Intent(this,MessengerService.class);
?????????????bindService(intent,mConnection,Context.BIND_AUTO_CREATE);
?????????}
?????????@Override
?????????protected?void?onDestroy()?{
?????????????unbindService(mConnection);
?????????????super.onDestroy();
?????????}
????}
四、使用AIDL通信

上面的Messenger來(lái)進(jìn)行進(jìn)程間通信的方法,如果大量的消息同時(shí)發(fā)送到服務(wù)端,服務(wù)端仍然只能一個(gè)個(gè)處理,如果有大量的并發(fā)請(qǐng)求,那么用Messenger就不太合適了。
所以,我們可能需要跨進(jìn)程調(diào)用服務(wù)端的方法,這種情形用Messenger就無(wú)法做到了,但是我們可以使用AIDL來(lái)實(shí)現(xiàn)跨進(jìn)程的方法調(diào)用。

這里,就不寫出AIDL的實(shí)現(xiàn)方式了,這個(gè)示例網(wǎng)絡(luò)資源很多。

五、使用ContentProvider

ContentProvider是Android中提供的專門用于不同應(yīng)用間進(jìn)行數(shù)據(jù)共享的方式,從這一點(diǎn)來(lái)看,它天生就適合進(jìn)程間通信。和Messenger一樣,ContentProvider的底層實(shí)現(xiàn)同樣也是Binder。

六、使用使用Socket

我們通過(guò)Socket來(lái)實(shí)現(xiàn)進(jìn)程間的通信。Socket也稱為“套接字”,是網(wǎng)絡(luò)通信中的概念,它分為流式套接字和用戶數(shù)據(jù)報(bào)套接字兩種,分別對(duì)應(yīng)于網(wǎng)絡(luò)的傳輸控制層中的TCP和UDP協(xié)議。TCP協(xié)議是面向連接的協(xié)議,提供穩(wěn)定的雙向通信功能,TCP連接的建立需要經(jīng)過(guò)“三次握手”才能完成,為了提供穩(wěn)定的數(shù)據(jù)傳輸功能,其本身提供了超時(shí)重傳機(jī)制,因此具有很高的穩(wěn)定性;而UDP是無(wú)連接的,提供不穩(wěn)定的單向通信功能,當(dāng)然UDP也可以實(shí)現(xiàn)雙向通信功能。在性能上,UDP具有更好的效率,其缺點(diǎn)是不保證數(shù)據(jù)一定能夠正確傳輸,尤其是在網(wǎng)絡(luò)擁塞的情況下。

總之,上面六種都可以實(shí)現(xiàn)進(jìn)程間通信的,具體可以根據(jù)自己的需求來(lái)選擇合適的方式。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/69035.html

相關(guān)文章

  • 02.AndroidIPC機(jī)制問(wèn)題

    摘要:中為何新增來(lái)作為主要的方式運(yùn)行機(jī)制是怎樣的機(jī)制有什么優(yōu)勢(shì)運(yùn)行機(jī)制是怎樣的基于通信模式,除了端和端,還有兩角色一起合作完成進(jìn)程間通信功能。 目錄介紹 2.0.0.1 什么是Binder?為什么要使用Binder?Binder中是如何進(jìn)行線程管理的?總結(jié)binder講的是什么? 2.0.0.2 Android中進(jìn)程和線程的關(guān)系?什么是IPC?為何需要進(jìn)行IPC?多進(jìn)程通信可能會(huì)出現(xiàn)什么問(wèn)...

    Donne 評(píng)論0 收藏0
  • Android IPC機(jī)制(一)——綁定Service實(shí)現(xiàn)本地通信

    摘要:而使用綁定的方式啟動(dòng)則可以實(shí)現(xiàn)之間的通信。下面就講述一下綁定實(shí)現(xiàn)本地通信的流程。單擊調(diào)用方法并且解除綁定。注意解除綁定事件只能執(zhí)行一次,否則程序會(huì)崩潰。 寫作原因:跨進(jìn)程通信的實(shí)現(xiàn)和理解是Android進(jìn)階中重要的一環(huán)。下面博主分享IPC一些相關(guān)知識(shí)、操作及自己在學(xué)習(xí)IPC過(guò)程中的一些理解。 這一章是為下面的Messenger和AIDL的使用做準(zhǔn)備,主要講解Android Servic...

    GitCafe 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<