进程间通信IPC
IPC是 Inter-Proscess Communication的缩写,含义为进程间的通讯或者跨进程通讯,是指两个进程之间进行数据交换的过程。按操作系统的中的描述,线程是CPU调度最小的单元,同时线程是一种有限的系统资源,而进程是指一个执行单元,在PC和移动设备上指一个程序或者一个应用。一个进程可以包含多个线程,因此进程和线程是包含于被包含的关系。
为什么要使用多进程,一个进程所分配的内存有限,为了获取更大的内存,往往把一些耗内存的操作放到其他进程之中,往往把耗时操作放到不同线程之中,题外话:I/O操作为耗时操作,计算则为耗内存操作。
AIDL
AIDL是Android中IPC(Inter-Process Communication)方式中的一种,AIDL是Android Interface definition language的缩写,是多client且多线程的。
(1)新建一个AIDL文件
(2)在AIDL的接口文件中创建所需方法
interface IMyAIDL {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void addName();
List<String> getNameList();
}
(3)编写服务端代码
public class ServeService extends Service{
private List<String> names;
private IBinder mIBinder = new IMyAIDL.Stub(){
@Override
public void addName(String name) throws RemoteException {
names.add(name);
}
@Override
public List<String> getNameList() throws RemoteException {
return names;
}
};
@Nullable
@Override
public IBinder onBind(Intent intent) {
names = new ArrayList<>();
return mIBinder;
}
}
(4)在客户端实现ServiceConnection接口,在这里拿到AIDL类
private IMyAIDL mAidl;
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//连接后拿到 Binder,转换成 AIDL,在不同进程会返回个代理
mAidl = IMyAidl.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
mAidl = null;
}
};
注意:在Manifests中把服务端Service放到其他进程中
<service android:name=".ClientService"
android:process="other"/>
(5)在客户端中绑定服务端Service
Intent intent = new Intent(getApplicationContext(), ServeService.class);
bindService(intent, mConnection, BIND_AUTO_CREATE);
(6)拿到AIDL类后,我们就可以通过调用AIDL中的方法来实现跨进程通信了
List<String> nameList = mAidl.getNameList();
mAidl.addName("张国荣");
Messenger
Messenger跨进程传递消息的机制和Handler类似,使用较为简单。使用Messenger的好处就是不用单独创建新的文件来传递消息。其底层实现和AIDL是一样的,且Messenger是一种较为轻量级的IPC方案。
(1)服务端代码
public class MessengerService extends Service {
/**
* 服务端Messenger
*/
@SuppressLint("HandlerLeak")
Messenger mMessenger = new Messenger(new Handler() {
@Override
public void handleMessage(final Message msg) {
if (msg != null && msg.what == 1) {
if (msg.getData() == null) {
return;
}
String content = (String) msg.getData().get("content"); //接收客户端的消息
Log.d("cc", "Message from client: " + content);
//回复消息给客户端
Message replyMsg = Message.obtain();
replyMsg.what = 2;
Bundle bundle = new Bundle();
bundle.putString("content", "收到了 over!");
replyMsg.setData(bundle);
try {
msg.replyTo.send(replyMsg); //回信
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
});
@Nullable
@Override
public IBinder onBind(final Intent intent) {
return mMessenger.getBinder();
}
}
(2)客户端代码
public class IPCTestActivity extends BaseActivity {
//服务端的 Messenger
private Messenger mServerMessenger;
/**
* 客户端的 Messenger
*/
@SuppressLint("HandlerLeak")
Messenger mClientMessenger = new Messenger(new Handler() {
@Override
public void handleMessage(final Message msg) {
if (msg != null && msg.what == 2){
if (msg.getData() == null){
return;
}
String content = (String) msg.getData().get("content");
Log.d("cc", "message from service:"+content);
}
}
});
private ServiceConnection mMessengerConnection = new ServiceConnection() {
@Override
public void onServiceConnected(final ComponentName name, final IBinder service) {
mServerMessenger = new Messenger(service);
}
@Override
public void onServiceDisconnected(final ComponentName name) {
mServerMessenger = null;
}
};
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindMessengerService();
}
/**
* 绑定service
*/
private void bindMessengerService() {
Intent intent = new Intent(this, MessengerService.class);
bindService(intent, mMessengerConnection, BIND_AUTO_CREATE);
sendMsg();
}
/**
* 客户端发送消息给service
*/
public void sendMsg() {
String msgContent ="我是客户端 收到请回话over!";
Message message = Message.obtain();
message.what = 1;
Bundle bundle = new Bundle();
bundle.putString("content", msgContent);
message.setData(bundle);
message.replyTo = mClientMessenger; //指定回信人是客户端定义的
try {
mServerMessenger.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
/**
* 销毁时解绑service
*/
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(mMessengerConnection);
}
}
(3)回传消息(回信)
msg.replyTo.send(replyMsg); //回信
msg.replyTo其实也是一个Messenger,它其实就是发送消息方的Messenger,在传递消息时它把本身也传递了过来,我们可以通过它来回传消息。
Messenger和AIDL的区别
Messenger的本质其实也是AIDL只不过是进行了封装,Messenger只能用于传递数据,无法调用服务端的方法,而AIDL即可以传递数据也可以调用服务端方法,这也是Messenger和AIDL的本质区别。Messenger相较于AIDL更轻量级但是没有AIDL灵活,Messenger是以串行的方式处理客户端发来的消息,当消息多的时候就就不合适了,而AIDL是可以并发处理客户端传来的消息。根据不同情况我们需要选择不同解决办法。
跨进程通信的其他方法:
Android实现跨进程通信其实还有很多其他的方法Content Provider,Broadcast,HermesEventBus(第三方开源库),文件共享,如果有需要可以了解一下。