1. 實(shí)現(xiàn)IPC(跨進(jìn)程)方法一 Bundle
Bundle可以通過Intent在跨進(jìn)程時(shí)帶過去,它支持基本數(shù)據(jù)類型,實(shí)現(xiàn)了Parcelable接口的對(duì)象停团,實(shí)現(xiàn)了Serializable接口的對(duì)象以及其他一些Android支持的特殊對(duì)象喊递。
2. 特殊場(chǎng)景
A進(jìn)程進(jìn)行一個(gè)計(jì)算,計(jì)算完成后啟動(dòng)B進(jìn)程的一個(gè)組件并把計(jì)算結(jié)果傳遞給B進(jìn)程蹬癌。問題是該結(jié)果不支持放入Bundle。
思考解決方式如下:A進(jìn)程啟動(dòng)B進(jìn)程的服務(wù)完成計(jì)算虹茶,B進(jìn)程的服務(wù)把計(jì)算結(jié)果給目標(biāo)組件逝薪。
3. 實(shí)現(xiàn)IPC(跨進(jìn)程)方法二 文件共享
兩個(gè)進(jìn)程讀寫同一文件可以實(shí)現(xiàn)跨進(jìn)程通信。windows上蝴罪,一個(gè)文件如果被加了排斥鎖將會(huì)導(dǎo)致其他進(jìn)程無法對(duì)其進(jìn)行訪問董济,包括讀寫。而Android是基于Linux的要门,使得其并發(fā)讀寫文件沒有限制感局。所以文件共享的方式要考慮并發(fā)問題。下面的代碼是MainActivity中序列化對(duì)象到文件暂衡,不同進(jìn)程的SecondActivity反序列化文件到對(duì)象询微。
// 序列化
try {
User user = new User(110, "allen");
File cache = new File(getCacheDir(), "cache.txt");
if (!cache.exists()) {
cache.createNewFile();
}
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(cache.getAbsoluteFile()));
out.writeObject(user);
out.close();
Log.e("aaa","---------"+user.toString());
} catch (IOException e) {
e.printStackTrace();
}
// 反序列化
try {
File cache = new File(getCacheDir(), "cache.txt");
if (!cache.exists()) {
cache.createNewFile();
}
ObjectInputStream in = new ObjectInputStream(new FileInputStream(cache.getAbsoluteFile()));
User newUser = (User) in.readObject();
in.close();
Log.e("aaa","---------"+newUser.toString());
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
文件類型沒有要求,比如txt的狂巢,xml的撑毛。但SharedPreferences是個(gè)例外,SharedPrefrences是Android提供的輕量級(jí)存儲(chǔ)方案唧领,它以鍵值對(duì)的方式來存儲(chǔ)數(shù)據(jù)藻雌,在底層實(shí)現(xiàn)上采用了xml文件來存儲(chǔ)。其目錄位于/data/data/packageName/shared_prefs目錄下斩个。從本質(zhì)上來說胯杭,SharedPreference也屬于文件的一種,但是對(duì)于系統(tǒng)對(duì)它的讀寫有一定的緩存策略受啥,即在內(nèi)存中會(huì)有一份SharedPreference文件的緩存做个。因此在多進(jìn)程模式下,系統(tǒng)對(duì)它的讀寫就變得不可靠滚局。因此不建議進(jìn)程間通信使用SharedPreference居暖。
3. Messenger簡介
Messanger可以翻譯為信使,顧名思義藤肢,通過它可以在不同的進(jìn)程中傳遞Message對(duì)象太闺。它是一種輕量級(jí)的IPC方案,它的底層實(shí)現(xiàn)了AIDL嘁圈。(書中說是根據(jù)構(gòu)造方法的寫法和aidl相似省骂,有些牽強(qiáng))蟀淮。
下面看下Messenger的代碼:
public final class Messenger implements Parcelable {
private final IMessenger mTarget;
public Messenger(Handler target) {
mTarget = target.getIMessenger();
}
public void send(Message message) throws RemoteException {
mTarget.send(message);
}
public IBinder getBinder() {
return mTarget.asBinder();
}
// ...
public Messenger(IBinder target) {
mTarget = IMessenger.Stub.asInterface(target);
}
}
重點(diǎn)還是IMessenger是個(gè)aidl接口。用everything搜一下可以搜到以下結(jié)果:
4. 簡單Messenger跨進(jìn)程實(shí)現(xiàn)
服務(wù)端:
public class MessengerService extends Service {
private Handler messengerHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 0:
String text = msg.getData().getString("msg");
Log.e("aaa", text);
break;
}
}
};
private Messenger messenger = new Messenger(messengerHandler);
public MessengerService() {
}
@Override
public IBinder onBind(Intent intent) {
return messenger.getBinder();
}
}
客戶端:
public class MessengerActivity extends AppCompatActivity {
Messenger messenger;
ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
messenger = new Messenger(service);
// 發(fā)消息
Message msg = Message.obtain();
msg.what = 0;
Bundle bundle = new Bundle();
bundle.putString("msg", "hello, this is client.");
msg.setData(bundle);
try {
messenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_messenger);
Intent intent = new Intent(this, MessengerService.class);
bindService(intent, serviceConnection, BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(serviceConnection);
}
}
Service定義在單獨(dú)的進(jìn)程中
<service
android:name="._2activity.Messenger.MessengerService"
android:enabled="true"
android:exported="true"
android:process=":remote" />
Messenger支持的數(shù)據(jù)類型實(shí)際是Message支持的數(shù)據(jù)類型钞澳,Message支持Bundle灭贷,所以適用性很強(qiáng)。
5. 實(shí)現(xiàn)客戶端發(fā)信息并且服務(wù)端響應(yīng)
上面的例子中服務(wù)端定義了接受消息的Messenger(也就是參數(shù)是Handler的)略贮,客戶端通過Binder拿到服務(wù)端的Messenger,然后用服務(wù)端的Messenger發(fā)消息給服務(wù)端仗岖。同樣逃延,服務(wù)端要回應(yīng),需要有客戶端接受消息的Messenger轧拄。
Activity中如下:
// 定義客戶端接受消息的Messenger
Messenger clientMessenger = new Messenger(new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.e("aaa",msg.getData().getString("reply"));
}
});
// 通過Message的replyto參數(shù)給服務(wù)端
// 發(fā)消息
Message msg = Message.obtain();
msg.what = 0;
Bundle bundle = new Bundle();
bundle.putString("msg", "hello, this is client.");
msg.setData(bundle);
// 把接收消息的Messenger通過Message的replyTo給服務(wù)端
msg.replyTo = clientMessenger;
messenger.send(msg);
服務(wù)端接收消息后揽祥,拿到客戶端的Messenger,再給客戶端發(fā)消息檩电。
private Handler messengerHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 0:
String text = msg.getData().getString("msg");
Log.e("aaa", text);
// 服務(wù)端回應(yīng)
Messenger clientMessenger = msg.replyTo;
Message message = Message.obtain();
Bundle bundle = new Bundle();
bundle.putString("reply","收到收到已收到");
message.setData(bundle);
try {
clientMessenger.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
}
}
};
6. 總結(jié)
Messenger很強(qiáng)大拄丰,它是實(shí)現(xiàn)輕量級(jí)IPC的方案。在普通開發(fā)中俐末,還可以用于Service調(diào)Activity中的方法料按,或者Activity調(diào)Service中的方法。之前說Activity調(diào)Service中的方法通過Binder卓箫,Service調(diào)Activity中的方法通過廣播载矿,這里又加了一種方案。
另外烹卒,Messenger一次發(fā)送一個(gè)請(qǐng)求闷盔,是串行,不存在并發(fā)旅急。因此服務(wù)端不需要考慮線程同步問題逢勾。