Android IPC 之Messenger

来源:互联网 发布:linux avi 转mp4 编辑:程序博客网 时间:2024/05/22 15:16

出去旅游的计划因为过年买不到火车票就泡汤了,只有过来写博客玩了。

一:概述

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开发艺术探索》

加个好友共同学习(不是公众号):

这里写图片描述

因为小弟水平有限,如果有写的有问题,希望指出。

0 0
原创粉丝点击