您的位置:首页 > 移动开发 > Android开发

Android IPC 之Messenger

2016-01-15 18:11 429 查看
出去旅游的计划因为过年买不到火车票就泡汤了,只有过来写博客玩了。

一:概述

ipc 就是进程间通信啊。

Android上进程间通信的方式有很多啊

以下就有:

[code]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在同一个进程中所以在清单文件中这样写:

[code]   <service
            android:name=".MessengerService"
            android:enabled="true"
            android:exported="true"
            android:process=":remote" />


android:process=”:remote”

是开启一个全新的进程开始运行这个service,“:”的意思是指当前的进程名字需要加上当前的包名,并且是属于当前应用包名的私有进程。

当年一个组件跑在一个全新的进程中的时候,系统会为这个进程分配一个独立的虚拟机,所以不能用我们平时普通的方式进行一个数据共享了。

使用Messager比较简单。

我们先看看Service端

新建一个Messenger:

[code]  private Messenger MyMessager = new Messenger(new MessengerHandler(MessengerService.this));


再来看看我们的Hanlder:

[code]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传递数据给服务端。

[code]  @Override
    public IBinder onBind(Intent intent) {
        return MyMessager.getBinder();
    }


我们在来看看客户端的具体实现:

也还是新建一个Messenger,这个Messenger是用来在请求服务端的时候顺便传过去的。不是用来请求的那个Messenger哦,用来请求服务端的Messenger稍后会说道。

然后我们绑定service

[code]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。

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

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



因为小弟水平有限,如果有写的有问题,希望指出。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: