出去旅游的计划因为过年买不到火车票就泡汤了,只有过来写博客玩了。
一:概述
ipc 就是进程间通信啊。
Android上进程间通信的方式有很多啊
以下就有:
1.bundle 只能传输bundle支持的数据
2.文件共享 不适合高并发,
3.aidl 支持一对多的并发通信(下篇博客写这个),需要处理线程同步问题。
4.Messenger 一对多的串行通信,并且是以message为载体传输
5.contentprovider
6.socket 将socket 访问第ip地址改成本地就可以了。
一个Messenger的例子:
通过Messenger传递数据给 service ,然后service接收到数据后再回应client(Activity)
Messenger 是对AIDL 的封装。
二:源码解读
首先我们先新建一个Service,为了不让他和Activity在同一个进程中所以在清单文件中这样写:
<service
android:name=".MessengerService"
android:enabled="true"
android:exported="true"
android:process=":remote" />
android:process=”:remote”
是开启一个全新的进程开始运行这个service,“:”的意思是指当前的进程名字需要加上当前的包名,并且是属于当前应用包名的私有进程。
当年一个组件跑在一个全新的进程中的时候,系统会为这个进程分配一个独立的虚拟机,所以不能用我们平时普通的方式进行一个数据共享了。
使用Messager比较简单。
我们先看看Service端
新建一个Messenger:
private Messenger MyMessager = new Messenger(new MessengerHandler(MessengerService.this));
再来看看我们的Hanlder:
private static class MessengerHandler extends Handler {
Context context;
MessengerHandler(Context ctx){
context = ctx;
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
Toast.makeText(context,"MessengerService : "+msg.getData().get("msg") , Toast.LENGTH_SHORT).show();
Messenger client = msg.replyTo;
Message replyMessage = Message.obtain(null,2);
Bundle bundle = new Bundle();
bundle.putString("reply","我是服务端,消息收到");
replyMessage.setData(bundle);
try{
client.send(replyMessage);
}catch(Exception e){
}
break;
default:
super.handleMessage(msg);
break;
}
}
}
handler是接收到数据后做的一些处理,弹了一个toast,然后通过
Messenger client = msg.replyTo;
得到从client端传过来的一个Messenger对象,然后通过这个对象返回数据给client。
在服务端新建了一个Messenger对象然后在 onBind 函数中返回了给client(activity) ,然后在client中通过这个Messenger传递数据给服务端。
@Override
public IBinder onBind(Intent intent) {
return MyMessager.getBinder();
}
我们在来看看客户端的具体实现:
也还是新建一个Messenger,这个Messenger是用来在请求服务端的时候顺便传过去的。不是用来请求的那个Messenger哦,用来请求服务端的Messenger稍后会说道。
然后我们绑定service
Intent intent = new Intent(MessengerActivity.this,MessengerService.class);
bindService(intent,mConnection,BIND_AUTO_CREATE);
这样service中会调用onBind方法,那么在 就可以得到从服务端回调的IBinder,然后转型成Messenger,就可以了,注意我们是用Message传递数据的哦,需要实例化一个Message对象,注意我们在这里还有
msg.replyTo = mGetReplyMessenger;
这句就是将上面说的顺便传递给服务端的那个Messenger,他的作用是服务端想回应我们的时候就使用这个Messenger将数据从服务端回传到client。
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = new Messenger(service);
Message msg = Message.obtain(null,1);
Bundle bundle = new Bundle() ;
bundle.putString("msg","client send to service");
msg.setData(bundle);
msg.replyTo = mGetReplyMessenger;
try{
mService.send(msg);
}catch (Exception e){
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
好了,大体上Messenger差不多了,这里小小总结下下。
首先需要bindservice(),然后将回调回来的IBinder,转型成Messenger,使用这个Messenger来请求服务端,但是为了服务端处理完了数据后能回应,所以请求的时候需要传递过去一个Messenger。
服务端接收到了客户端的请求后处理数据,然后再使用传递过来的Messenger (msg.replyTo),回应客户端。
参考书籍《Android开发艺术探索》
加个好友共同学习(不是公众号):
因为小弟水平有限,如果有写的有问题,希望指出。