天天看點

跨程序通信使用總結(一)_跨程序通信基礎篇

跨程序通信基礎篇

含義:

跨程序通信,是指兩個程序之間資料交換的過程,英文全稱 Inter-Process Communication 縮寫IPC

程序和線程的關系:

在移動裝置上,一個程式或者一個應用,就是一個程序,一個程序裡面可以包含多個線程

(例如:一個應用裡面有一個主線程(用于更新UI)和多個子線程(執行耗時的任務))

開啟多線程的方法:

在Android中開啟多程序隻有一種方法: 那就是給4大元件(Activity,Service,Receiver,ContentProvider)在Menifest中指定android:process屬性,除此之外沒有其他的方法(通過JNI在native層去fork一個新程序除外)

執行個體1如下:

<activity
    android:name=".activity.Main2Activity"
    android:process=":remote1" />
           

執行個體2如下:

<activity
    android:name=".activity.Main3Activity"
    android:process="com.hlj.demo.remote2" />
           

說明:

1.首先執行個體1中 ":“的含義是指:這是一種簡寫

a.目前的程序名稱前面要附加上目前的包名 程序完整名稱:com.hlj.demo:remote1

b.以”:"開頭的程序屬于目前應用的私有程序,其他應用的元件不可以和它跑在同一個程序中

2,執行個體2中的程序名稱是一種完整的命名方式,不會附加包名資訊,其次它屬于全局程序,其他應用通過ShareUID方式可以和它跑在同一個程序中.(2個應用的簽名也要相同)

注意:

程式入口MainActivity,預設沒有給它process屬性,那麼它就運作在預設的程序中,預設的程序名稱是包名,如果給它指定了process屬性,那麼它就運作在該指定程序當中

如何檢視自己開啟了多少個程序呢,studio如下圖所示:

跨程式通信使用總結(一)_跨程式通信基礎篇

運作在同一個程序中的元件是屬于同一個虛拟機和同一個Application,可以共享Applicaiton下的資料,運作在不同程序中的元件是屬于2個不同的虛拟機和2個不同的Application,2個不同的Application資料是不能互通的

IPC的基礎概念: Serializable接口,Parcelable接口,Binder

Serializable接口:Serializable是java所提供的一個序列化的接口,它是一個空接口,為對象提供序列化和反序列化操作

//實作Serializable接口即可
public class UserBean implements Serializable{
    private static final long serialVersionUID=1L;
    public String name;
}
           
UserBean user = new UserBean();
user.name = "hao123";
if (!StrUtils.IsKong(Environment.getExternalStorageDirectory() + "/" + "demo")) {
      String baseExternalStoragepath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + "demo";
      baseDirectory = new File(baseExternalStoragepath);
      if (!baseDirectory.exists()) {
          //先建立檔案夾
          baseDirectory.mkdirs();
      }
      //再建立檔案
      File wejian = new File(baseDirectory.getPath() + "/" + "user.txt");
      if (!wejian.exists()) {
          wejian.createNewFile();
      }
      //序列化到檔案中
      ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(wejian));
      out.writeObject(user);
      out.flush();
      out.close();   
  }


 //反序列化,從檔案中讀取檔案
  File wejian=new File(baseDirectory.getPath()+"/"+"user.txt");
  ObjectInputStream in=new ObjectInputStream(new FileInputStream(wejian));
  UserBean user=(UserBean)in.readObject();
  in.close();
           

注意:

序列化和反序列化需要讀寫檔案,是以需要在清單檔案配置讀寫權限,大于6.0的裝置還要動态申請權限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
           

serialVersionUID:

一般來說我們應該手動指定serialVersionUID的值,這樣做的好處是:當版本更新後,我們可能删除了某個成員變量也可能增加了一些新的成員變量,但指定了這個值以後,反序列化還是可以成功,程式可以最大限度的恢複資料,如果不指定serialVersionUID的值的話,程式會挂掉,但是如果類結構發生了非正常性的改變,例如修改了成員變量的類型結構,這種毀滅性的改變後,反序列化還是會失敗,因為無法從老版本的資料中還原一個新的類型結構的對象

注意:

1,靜态成員屬于類不屬于對象,是以不會參與序列化的過程

2,用transient關鍵字标記的成員變量不會參與序列化的過程

Parcelable接口

Parcelable 是android中提供的新的序列化方式,隻要實作這個接口,一個類的對象就可以實作序列化,并且可以通過Intent和Binder傳輸

執行個體如下:

public class User2 implements Parcelable {
    public  int age;
    //體重
    public  int weight;
    public  String name;
    public Book book;

    public User2(){
    
    }

    public User2(Parcel in) {
    //注意:這裡讀取字段的屬性要和寫入字段的順序一樣 age,weight,name,book
        age=in.readInt();
        weight=in.readInt();
        name=in.readString();
        //由于book是另一個序列化對象,是以它的反序列化的過程要傳遞目前上下文類加載器
        book= in.readParcelable(Thread.currentThread().getContextClassLoader());
        
    }

    //studio會自動生成這裡
    public static final Creator<User2> CREATOR = new Creator<User2>() {
        @Override
        public User2 createFromParcel(Parcel in) {
            return new User2(in);
        }

        @Override
        public User2[] newArray(int size) {
            return new User2[size];
        }
    };

    //studio會自動生成這裡
    @Override
    public int describeContents() {
        return 0;
    }


    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(age);
        dest.writeInt(weight);
        dest.writeString(name);
        dest.writeParcelable(book,0);
    }
}

           

說明:

1,從Parcel in裡面讀取字段的順序一定要和writeToParcel字段的順序一樣(否則同一個類型的字段例如age和weight資料會搞混)

2,由于Book是另一個序列化對象,是以它的反序列化的過程要傳遞目前上下文類加載器

Parcelable接口和Serializable接口的比較

共同點:都能實作序列化并且都可用于Intent間的資料傳遞

不同點:Serializable是java中提供的接口,使用起來更加簡單,但是開銷很大,需要大量的IO操作,Parcelable是android中的序列化方式,是以更适用與android平台,缺點是使用起來稍微麻煩一點,優點是效率高

Binder:

直覺來講,Binder是android中的一個類,它實作了IBinder接口.從IPC的角度來講,Binder是Android中的一種跨程序通信方式,從AndroidFramework角度來講,Binder是ServiceManager連接配接各種Manager(ActivityNamager,WindowManger等等)的橋梁;從Android應用層來講,Binder是用戶端和服務端進行通信的媒介,當binderService的時候,服務端會傳回一個包含服務端業務調用的Binder對象,通過這個Binder對象,用戶端就可以擷取服務端提供的服務或者資料,這裡的服務包含普通的服務和基于AIDL的服務,普通的service服務不涉及程序間通信,主要是AIDL會涉及binder的核心

結尾:

下一篇會總結跨程序通信的幾種方式,盡情期待啦~^^

繼續閱讀