这两天在看binder,无意间在文档看到messenger这么个东西,感觉这个东西还挺有意思的,给大家分享一下。

平时一说进程间通讯,大家都会想到AIDL,其实messenger和AIDL作用一样,都可以进行进程间通讯。它是基于消息的进程间通信,就像子线程和UI线程发送消息那样,是不是很简单,还不用去写AIDL文件,是不是有点小爽。哈哈。

此外,还支持记录客户端对象的Messenger,然后可以实现一对多的通信;甚至作为一个转接处,任意两个进程都能通过服务端进行通信。

与 AIDL 比较:

  当您需要执行 IPC 时,为您的接口使用 Messenger 要比使用 AIDL 实现更加简单,因为 Messenger 会将所有服务调用排入队列,而纯粹的 AIDL 接口会同时向服务发送多个请求,服务随后必须应对多线程处理。

  对于大多数应用,服务不需要执行多线程处理,因此使用 Messenger 可让服务一次处理一个调用。如果您的服务必须执行多线程处理,则应使用 AIDL 来定义接口。

接下来看下怎么用:

服务端:

1.创建一个handler对象,并实现hanlemessage方法,用于接收来自客户端的消息,并作处理

2.创建一个messenger(送信人),封装handler

3.用messenger的getBinder()方法获取一个IBinder对象,通过onBind返回给客户端

客户端:

1.在activity中绑定服务

2.创建ServiceConnection并在其中使用 IBinder 将 Messenger实例化

3.使用Messenger向服务端发送消息

4.解绑服务

5.服务端中在 handleMessage() 方法中接收每个 Message

这样,客户端并没有调用服务的“方法”。而客户端传递的“消息”(Message 对象)是服务在其 Handler 中接收的。

上面实现的仅仅是单向通信,即客户端给服务端发送消息,如果我需要服务端给客户端发送消息又该怎样做呢?

其实,这也是很容易实现的,下面就让我们接着上面的步骤来实现双向通信吧

1.在客户端中创建一个Handler对象,用于处理服务端发过来的消息

2.创建一个客户端自己的messenger对象,并封装handler。

3.将客户端的Messenger对象赋给待发送的Message对象的replyTo字段

4.在服务端的Handler处理Message时将客户端的Messenger解析出来,并使用客户端的Messenger对象给客户端发送消息

这样就实现了客户端和服务端的双向通信了。

注意:注:Service在声明时必须对外开放,即android:exported="true"

是不是看的头晕,忘掉吧,直接看下面。

看一个简单的例子

 package com.zixue.god.myapplication;

 import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.widget.Toast; //服务端service
public class MyService extends Service {
private static final int CODE = 1;
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
} //创建一个送信人,封装handler
private Messenger mMessenger = new Messenger(new Handler() {
@Override
public void handleMessage(Message msg) {
Message toClient = Message.obtain();
switch (msg.what) {
case CODE:
//接收来自客户端的消息,并作处理
int arg = msg.arg1;
Toast.makeText(getApplicationContext(),arg+"" , Toast.LENGTH_SHORT).show();
toClient.arg1 = 1111111111;
try {
//回复客户端消息
msg.replyTo.send(toClient);
} catch (RemoteException e) {
e.printStackTrace();
}
}
super.handleMessage(msg);
}
});
}

//客户端

 package com.zixue.god.fuck;

 import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast; public class MainActivity extends AppCompatActivity {
private boolean mBond;
private Messenger serverMessenger;
private MyConn conn; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//绑定服务
Intent intent = new Intent();
intent.setAction("com.zixue.god.myapplication.server");
conn = new MyConn();
bindService(intent, conn, BIND_AUTO_CREATE);
Button button = (Button) findViewById(R.id.bt);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Message clientMessage = Message.obtain();
clientMessage.what = 1;
clientMessage.arg1 = 12345;
try {
clientMessage.replyTo = mMessenger;
serverMessenger.send(clientMessage);
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
} private class MyConn implements ServiceConnection { @Override
public void onServiceConnected(ComponentName name, IBinder service) {
//连接成功
serverMessenger = new Messenger(service);
Log.i("Main", "服务连接成功");
mBond = true;
} @Override
public void onServiceDisconnected(ComponentName name) {
serverMessenger = null;
mBond = false;
}
}
private Messenger mMessenger = new Messenger(new Handler(){
@Override
public void handleMessage(Message msg) {
Toast.makeText(getApplicationContext(),msg.arg1+"",Toast.LENGTH_SHORT).show();
super.handleMessage(msg);
}
});
@Override
protected void onDestroy() {
if (mBond) {
unbindService(conn);
}
super.onDestroy();
} }

这样就实现了客户端和服务端双向通信,是不是很简单呢。

  其实messenger底层也是AIDL。客户端和服务端通讯,就是普通的AIDL,客户端实例化stub之后,通过stub的send方法把消息发到服务端。服务端和客户端通讯:服务端通过解析message的replyto,获得客户端的stub,然后通过send方法发送到客户端。有精力的可以去翻一下源码。

Android进程间通讯之messenger的更多相关文章

  1. Android进阶笔记04:Android进程间通讯(IPC)之Messenger

    一. Android进程间通讯之Messenger 的引入 (1)引言:      平时一说进程间通讯,大家都会想到AIDL,其实messenger和AIDL作用一样,都可以进行进程间通讯.它是基于消 ...

  2. Android进程间通讯

    最近研究了一下Android进程间通讯,原来只是会用,但是只是会用是不行滴,就来研究一下. 刚开始看的时候,我的头是这么大,看了一夜的时候,头就变成这样了,,吓得宝宝赶紧上床休息了,. 先喝喝茶讲个故 ...

  3. Android 进程间通讯方式

    Android 进程间通讯方式 1.通过单向数据管道传递数据 管道(使用PipedWriter/ 创建PipedReader)是java.io包的一部分.也就是说,它们是一般的Java功能,而不是An ...

  4. Android-Android进程间通讯之messenger

    转自‘https://www.cnblogs.com/makaruila/p/4869912.html 平时一说进程间通讯,大家都会想到AIDL,其实messenger和AIDL作用一样,都可以进行进 ...

  5. Android(java)学习笔记232:Android进程间通讯(IPC)之AIDL

    一.IPC inter process communication  进程间通讯 二.AIDL android  interface  defination  language  安卓接口定义语言 满 ...

  6. Android(java)学习笔记175:Android进程间通讯(IPC)之AIDL

    一.IPC inter process communication  进程间通讯 二.AIDL android  interface  defination  language  安卓接口定义语言 满 ...

  7. android 进程间通信 messenger 是什么 binder 跟 aidl 区别 intent 进程间 通讯? android 消息机制 进程间 android 进程间 可以用 handler么 messenger 与 handler 机制 messenger 机制 是不是 就是 handler 机制 或 , 是不是就是 消息机制 android messenge

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha messenger 是什么 binder 跟 aidl 区别 intent 进程间 通讯 ...

  8. Android查缺补漏(IPC篇)-- Bundle、文件共享、ContentProvider、Messenger四种进程间通讯介绍

    本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8387752.html 进程间通讯篇系列文章目录: Android查缺补漏(IP ...

  9. Android查缺补漏(IPC篇)-- 进程间通讯基础知识热身

    本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8479282.html 在Android中进程间通信是比较难的一部分,同时又非常 ...

随机推荐

  1. Swift3新特性汇总

    之前 Apple 在 WWDC 上已将 Swift 3 整合进了 Xcode 8 beta 中,而本月苹果发布了 Swift 3 的正式版.这也是自 2015 年底Apple开源Swift之后,首个发 ...

  2. js中子页面父页面方法 变量相互调用

    (1)子页面调用父页面的方法或者变量: window.parent.方法()或者变量名window.parent相当于定位到父页面  之后的操作和在父页面中写代码一样写 window.parent.a ...

  3. 史上最全的maven的pom.xml文件详解

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...

  4. linux ps命令,查看进程cpu和内存占用率排序(转)

    使用以下命令查看: ps -aux | sort -k4,4n ps auxw --sort=rss ps auxw --sort=%cpu linux 下的ps命令 %CPU 进程的cpu占用率 % ...

  5. JAVA BigDecimal 小数点处理

    1,保留两位小数 方法一:{ double c=3.154215; java.text.DecimalFormat myformat=new java.text.DecimalFormat(" ...

  6. pip 安装插件慢的解决方法

    有的时候在服务器上使用pip3安装插件比较慢. 本人非常痛苦,后经指点使用国内的源就好了...效果杠杠的... 以下为使用方法: pip3 install paramiko -i http://mir ...

  7. vim简明教程

    在shell中新建一个文件 # vim a.txt vim有三种模式:一般模式.插入模式.底行模式 三种工作模式 1.命令模式 移动光标 hjkl yy 复制 nyy 从光标向下复制n行 0 移动光标 ...

  8. 攻城狮在路上(陆)-- hadoop分布式环境搭建(HA模式)

    一.环境说明: 操作系统:Centos6.5 Linux node1 2.6.32-431.el6.x86_64 #1 SMP Fri Nov 22 03:15:09 UTC 2013 x86_64 ...

  9. Conditional project or library reference in Visual Studio

    Conditional project or library reference in Visual Studio In case you were wondering why you haven’t ...

  10. ng1.3+表单验证<AngularJs>

    前一篇文章说过,ng1.3+以后对于表单验证有了优化,它不再需要一个详细的表达式状态创建元素显示或隐藏. 例如:我们在ng1.3之前的版本都需要如下写法: <div class="er ...