(六)Android的IPC機(jī)制的基礎(chǔ)

本文為Android的IPC相關(guān)知識整理,具體參考了

  • 《Android開發(fā)藝術(shù)探索》第二章 IPC機(jī)制

IPC,Inter-Process Communicatoin的縮寫。即為Android進(jìn)程間通信。


1,進(jìn)程與線程

  • 線程是CPU調(diào)度的基本單位,進(jìn)程一般指一個執(zhí)行單元,在移動設(shè)備上指一個應(yīng)用或者是一個程序。一個進(jìn)程包含一個或多個線程。
  • 在Android中,一個程序可以只有一個線程,即主線程,也叫UI線程。在UI線程中才能操作界面元素,而不能在UI線程中執(zhí)行大量耗時任務(wù),否則會造成ANR,Application not responding錯誤。

Android線程(Thread)間通信:

  • Handle和Looper配合,消息隊列機(jī)制。我們可以用AsyncTask類這個異步任務(wù)類。
  • 訪問其他應(yīng)用程序的Activity,通過Intent附帶信息
    IntentcallIntent= newIntent(Intent.ACTION_CALL,Uri.parse("tel:12345678");
    startActivity(callIntent);
  • ContentProvider,例如訪問系統(tǒng)相冊,通訊錄,短信等
  • Broadcast 廣播
  • AIDL,Android接口定義語言

Android進(jìn)程(Process)間通信:

  • Binder
  • Socket
  • 文件共享
  • ContentProvider
  • Intent
  • Messenger

2,Android中的多進(jìn)程

在Android中使用多進(jìn)程只有一種方法,即給四大組件在AndroidManifest中指定android:process屬性。

   <activity
         android:name="com.ryg.chapter_2.MainActivity"
         android:label="@string/app_name">
         <intent-filter>
             ....
         </intent-filter>
    </acitivty>
    <activity
         android:name="com.ryg.chapter_2.SecondAcitvity"
         android:process=":remote"/>
    <activity
         android:name="com.ryg.chapter_2.ThirdAcitvity"
         android:process="com.ryg.chapter.remote"/>

以上三個activity分別在以下進(jìn)程中:

  • com.ryg.chapter_2,沒有為組件指定process,那么這個組件就會運(yùn)行在默認(rèn)進(jìn)程中。
  • com.ryg.chapter_2:remote,冒號的含義是在當(dāng)前的進(jìn)程名上附加當(dāng)前的包名,此進(jìn)程屬于當(dāng)前應(yīng)用的私有進(jìn)程。
  • com.ryg.chapter_2.remote,進(jìn)程名不以冒號開頭的進(jìn)程屬于全局進(jìn)程,其他應(yīng)用通過ShareUID方式可以和它跑在同一個進(jìn)程中。

由于Android會為每一個進(jìn)程提供單獨(dú)的虛擬機(jī),不同的虛擬機(jī)在內(nèi)存分配上有不同的地址空間,因而在不同的虛擬機(jī)中訪問同一個類對象會產(chǎn)生多份副本。不同進(jìn)程的虛擬機(jī),Application,內(nèi)存空間都不一樣!?。?!相當(dāng)于兩個不同的應(yīng)用采用了SharedUID模式。

多進(jìn)程引起的問題:

  • 靜態(tài)成員和單例模式失效
  • 線程同步機(jī)制失效
  • SharedPreferences可靠性下降,其不支持兩個進(jìn)程同時執(zhí)行寫操作。
  • Application會多次重建

3,IPC基礎(chǔ)概念

當(dāng)我們需要通過Intent和Binder傳輸數(shù)據(jù)時,需要使用Serializable和Serializable接口來完成對象的序列化。
當(dāng)我們需要使對象持久化到存儲設(shè)備上時,需要使用Serializable來完成對象的持久化。

3.1 Serializable接口

這個是Java自帶的,很簡單但是內(nèi)存開銷大,只需要在類中加入serialVersionUID。適用于將對象序列化到存儲設(shè)備或者將對象序列化后通過網(wǎng)絡(luò)進(jìn)行傳輸。

    public class User implements Serializable{
          private static final serialVersionUID = 4132904873290147032L;

          public int userId;
          public String userName;
          public boolean isMale;
    }

序列化和反序列化過程

     //序列化
    User user = new User(0, "jake",true;);
    ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("cache.txt"));
    out.writeObject(user);
    out.close();

     //反序列化
    ObjectInputStream in= new ObjectInputStream(new FileInputStream("cache.txt"));
    User newUser = (User)in.readObject();
    in.close();

恢復(fù)后的newUser對象和user內(nèi)容完全一致,但不是同一對象。

為了避免反序列化失敗,serialVersionUID 一般應(yīng)該手動指定?。。?/strong>其實(shí)也可以不指定serialVersionUID ,但這樣的話是IDE自動根據(jù)類結(jié)構(gòu)去生成hash值,這樣的話我們對其的控制力就弱了,如果改變了類結(jié)構(gòu),就不能反序列化了?。。?!而手動指定serialVersionUID 可以最大限度恢復(fù)數(shù)據(jù)。

3.2 Parcelable接口

這個是Android獨(dú)有的,更適合用在Android平臺,效率高,但是用起來有點(diǎn)麻煩。

    public class User implements parcelable{
          public int userId;
          public String userName;
          public boolean isMale;
          
          public User(int userId, String userName, boolean isMale){
              this.userId = userId;
              this.userName = userName;
              this.isMale = isMale;
          }

          public Book book;
          
          //內(nèi)容描述
          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<user> CREATOR = new Parcelable.Creator<User>(){
                 //從序列化后的對象中創(chuàng)建原始對象
                 public User createFromParcel(Parcel in){
                      return new User(in); 
                }
               
                 //創(chuàng)建指定長度的原始對象
                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().getContextClassLoader());
          }
          
          
    }

3.3 Binder

  • 從IPC角度看,Binder是一種跨進(jìn)程通信方式。
  • 從Android Freamwork角度來說,Binder是ServiceManager連接各種Manager(ActivityManager、WindowManager)和相應(yīng)ManagerService的橋梁。
  • 從Android應(yīng)用層將,Binder是客戶端和服務(wù)器進(jìn)行通信的媒介。

Android開發(fā)中,Binder主要用在Service中,包括AIDL,Messenger。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容