Android 中的 IPC 方式一:使用 Bundle
前言
Android 中跨程序通訊的方式比較多,比如可以通過在 Intent 中附加 extras 來傳遞資訊,或者通過共享檔案的方式來共享資料,還可以採用 Binder 方式來跨程序通訊,另外,ContentProvider 天生就是支援跨程序訪問的,因此我們也可以採用它來進行 IPC。此外,通過網路通訊也是可以實現資料傳遞的,所以 Socket 也是可以實現 IPC 的。今天我們先來介紹一下通過使用 Bundle 的方式進行 IPC。
使用 Bundle
我們知道四大元件中的三大元件(Activity、Service、BroadcastReceiver)都是支援在 Intent 中傳遞 Bundle 資料的,由於 Bundle 實現了 Parcelable 介面,所以它可以方便地在不同的程序間傳輸。
基於這一點,當我們在一個程序中啟動了另一個程序的 Activity、Service 和 Receiver,我們就可以在 Bundle 中附加我們需要傳輸給遠端程序的資訊並通過 Intent 傳送出去。當然,我們傳輸的資料必須能夠被序列化,比如基本型別、實現了 Parcelable 介面的物件、實現了 Serializable 介面的物件以及一些 Android 支援的特殊物件。
A 程序中 MainActivity:
Intent intent = new Intent();
intent.setClass(MainActivity.this, SecondActivity.class );
User user = new User(0, "jake");
intent.putExtra("extra_user", (Serializable) user);
startActivity(intent);
B 程序中 SecondActivity:
@Override
protected void onResume() {
super.onResume();
User user = (User) getIntent().getSerializableExtra("extra_user");
Log.d(TAG, "user:" + user.toString());
}
其中 User 類:
public class User implements Serializable {
private static final long serialVersionUID = 519067123721295773L;
public int userId;
public String userName;
public User() {
}
public User(int userId, String userName) {
this.userId = userId;
this.userName = userName;
}
@Override
public String toString() {
return String.format(
"User:{userId:%s, userName:%s}",userId, userName);
}
}
Bundle 不支援的型別無法通過它在程序間傳遞。
除了直接傳遞資料這種典型的使用場景,它還有一種特殊的使用場景。比如 A 程序正在進行一個計算,計算完成後它要啟動 B 程序的一個元件並把計算結果傳遞給 B 程序,可是遺憾的是這個計算結果不支援放入到 Bundle 中,因此無法通過 Intent 來傳輸,這個時候如果我們使用其他的 IPC 方式就會略顯複雜。
可以考慮如下方式:
我們通過 Intent 啟動 B 的一個 Service 元件(比如 IntentService),讓 Service 在後臺進行計算,計算完畢後再啟動 B 程序中真正要啟動的目標元件,由於 Service 也執行在 B 程序中,所以目標元件就可以直接獲取計算記過,這樣一來就輕鬆解決了跨程序的問題。這種方式的核心思想在於將原本需要在 A 程序的計算任務轉移到 B 程序的後臺 Service 中去執行,這樣就成功地避免了程序間通訊問題,而且只用了很小的代價。