Android开发过程中,有的时候有IPC进程间通信的需求。
常常一提起进程间通信,首先会想到AIDL(Android Interface Definition Language,安卓接口定义语言)。
Bundle
Android四大组件中的三大组件(Activity、Service、Receiver)都是支持在Intent中传递Bundle数据的。由于Bundle实现了Parcelable接口,所以他可以方便的再不同进程间传入。
但是输入的数据类型必须能被够序列化,Bundle不知道的类型不能通过它在进程间通信。
一种特殊的使用场景:A进程正在进行一个计算,计算完成后要启动B进程中的一个组件,并把计算结果传递给B进程,可是不巧的是,计算结果不支持放入Bundle中,无法通过Intent进行传输,此时如果使用其他IPC方式可能会略显复杂。这时可用如下方式:通过Intent启动进程B的一个Service组件(比如IntentService),让Service在后台进行计算,计算完毕后再启动B进程中真正要启动的组件,由于Service也运行在B进程中,所以目标组件就可以直接获取计算结果。这种方式核心思想在于将原本需要在A进程的计算任务转移到B进程的后台Service中执行,这样就成功避免了进程间通信问题。
文件共享
文件共享也是一种进程间通信的方式,两个进程通过读/写同一个文件来交换数据。比如A进程把数据写入文件,B进程通过读取这个文件来获取数据。
不过,由于Android系统中,并发读写文件可以没有限制的进行,甚至两个线程同时对一个文件进行写操作也是允许的,这就有可能会出现问题。因此文件共享的方式也是有局限性的。所以要尽量避免并发读写这种情况的发送或者考虑使用线程同步来限制多个线程的写操作。
文件共享方式适合在对数据同步要求不搞的进程直接进行通信,并且要妥善处理并发读写的问题。
SharePreferences在进程间通信有很大的几率会丢失数据,不建议在进程间通信使用SharePreferences。
Messenger
Android开发中通过Messenger可以在不同进程中传递Message对象,在Message放入我们需要传递的数据,就可以轻松实现数据的进程间传递了。Messenger是一种轻量级的IPC方案,它的底层实现是了AIDL。在其源码中可以看到,里面使用了IMessenger.Stub.asInterface(target)
。
Messenger的使用方法很简单。
public final class Messenger implements Parcelable {
private final IMessenger mTarget;
/**
* Create a new Messenger pointing to the given Handler. Any Message
* objects sent through this Messenger will appear in the Handler as if
* {@link Handler#sendMessage(Message) Handler.sendMessage(Message)} had
* been called directly.
*
* @param target The Handler that will receive sent messages.
*/
public Messenger(Handler target) {
mTarget = target.getIMessenger();
}
public void send(Message message) throws RemoteException {
mTarget.send(message);
}
/**
* Retrieve the IBinder that this Messenger is using to communicate with
* its associated Handler.
*
* @return Returns the IBinder backing this Messenger.
*/
public IBinder getBinder() {
return mTarget.asBinder();
}
public boolean equals(Object otherObj) {
if (otherObj == null) {
return false;
}
try {
return mTarget.asBinder().equals(((Messenger)otherObj)
.mTarget.asBinder());
} catch (ClassCastException e) {
}
return false;
}
public int hashCode() {
return mTarget.asBinder().hashCode();
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel out, int flags) {
out.writeStrongBinder(mTarget.asBinder());
}
public static final Parcelable.Creator<Messenger> CREATOR
= new Parcelable.Creator<Messenger>() {
public Messenger createFromParcel(Parcel in) {
IBinder target = in.readStrongBinder();
return target != null ? new Messenger(target) : null;
}
public Messenger[] newArray(int size) {
return new Messenger[size];
}
};
public static void writeMessengerOrNullToParcel(Messenger messenger,
Parcel out) {
out.writeStrongBinder(messenger != null ? messenger.mTarget.asBinder()
: null);
}
public static Messenger readMessengerOrNullFromParcel(Parcel in) {
IBinder b = in.readStrongBinder();
return b != null ? new Messenger(b) : null;
}
/**
* Create a Messenger from a raw IBinder, which had previously been
* retrieved with {@link #getBinder}.
*
* @param target The IBinder this Messenger should communicate with.
*/
public Messenger(IBinder target) {
mTarget = IMessenger.Stub.asInterface(target);
}
具体使用情况请查看《IPC进程间通信的使用(二)——Messenger》
AIDL
ContentProvider
请查看《IPC进程间通信的使用(四)——ContentProvider》
Socket
注:本文章知识点来自学习《Android开发艺术探索》一书