转自‘https://www.cnblogs.com/makaruila/p/4869912.html

平时一说进程间通讯,大家都会想到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"

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

看一个简单的例子

 1 package com.zixue.god.myapplication;
2
3 import android.app.Service;
4 import android.content.Intent;
5 import android.os.Handler;
6 import android.os.IBinder;
7 import android.os.Message;
8 import android.os.Messenger;
9 import android.os.RemoteException;
10 import android.widget.Toast;
11
12 //服务端service
13 public class MyService extends Service {
14 private static final int CODE = 1;
15 public MyService() {
16 }
17 @Override
18 public IBinder onBind(Intent intent) {
19 return mMessenger.getBinder();
20 }
21
22 //创建一个送信人,封装handler
23 private Messenger mMessenger = new Messenger(new Handler() {
24 @Override
25 public void handleMessage(Message msg) {
26 Message toClient = Message.obtain();
27 switch (msg.what) {
28 case CODE:
29 //接收来自客户端的消息,并作处理
30 int arg = msg.arg1;
31 Toast.makeText(getApplicationContext(),arg+"" , Toast.LENGTH_SHORT).show();
32 toClient.arg1 = 1111111111;
33 try {
34 //回复客户端消息
35 msg.replyTo.send(toClient);
36 } catch (RemoteException e) {
37 e.printStackTrace();
38 }
39 }
40 super.handleMessage(msg);
41 }
42 });
43 }

//客户端

 1 package com.zixue.god.fuck;
2
3 import android.content.ComponentName;
4 import android.content.Intent;
5 import android.content.ServiceConnection;
6 import android.os.Bundle;
7 import android.os.Handler;
8 import android.os.IBinder;
9 import android.os.Message;
10 import android.os.Messenger;
11 import android.os.RemoteException;
12 import android.support.v7.app.AppCompatActivity;
13 import android.util.Log;
14 import android.view.View;
15 import android.widget.Button;
16 import android.widget.Toast;
17
18 public class MainActivity extends AppCompatActivity {
19 private boolean mBond;
20 private Messenger serverMessenger;
21 private MyConn conn;
22
23 @Override
24 protected void onCreate(Bundle savedInstanceState) {
25 super.onCreate(savedInstanceState);
26 setContentView(R.layout.activity_main);
27 //绑定服务
28 Intent intent = new Intent();
29 intent.setAction("com.zixue.god.myapplication.server");
30 conn = new MyConn();
31 bindService(intent, conn, BIND_AUTO_CREATE);
32 Button button = (Button) findViewById(R.id.bt);
33 button.setOnClickListener(new View.OnClickListener() {
34 @Override
35 public void onClick(View v) {
36 Message clientMessage = Message.obtain();
37 clientMessage.what = 1;
38 clientMessage.arg1 = 12345;
39 try {
40 clientMessage.replyTo = mMessenger;
41 serverMessenger.send(clientMessage);
42 } catch (RemoteException e) {
43 e.printStackTrace();
44 }
45 }
46 });
47 }
48
49 private class MyConn implements ServiceConnection {
50
51 @Override
52 public void onServiceConnected(ComponentName name, IBinder service) {
53 //连接成功
54 serverMessenger = new Messenger(service);
55 Log.i("Main", "服务连接成功");
56 mBond = true;
57 }
58
59 @Override
60 public void onServiceDisconnected(ComponentName name) {
61 serverMessenger = null;
62 mBond = false;
63 }
64 }
65 private Messenger mMessenger = new Messenger(new Handler(){
66 @Override
67 public void handleMessage(Message msg) {
68 Toast.makeText(getApplicationContext(),msg.arg1+"",Toast.LENGTH_SHORT).show();
69 super.handleMessage(msg);
70 }
71 });
72 @Override
73 protected void onDestroy() {
74 if (mBond) {
75 unbindService(conn);
76 }
77 super.onDestroy();
78 }
79
80 }

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

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

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

  1. Android Binder 进程间通讯机制梳理

    什么是 Binder ? Binder是Android系统中进程间通讯(IPC)的一种方式,也是Android系统中最重要的特性之一.Binder的设计采用了面向对象的思想,在Binder通信模型的四 ...

  2. Android进程间通讯之messenger

    这两天在看binder,无意间在文档看到messenger这么个东西,感觉这个东西还挺有意思的,给大家分享一下. 平时一说进程间通讯,大家都会想到AIDL,其实messenger和AIDL作用一样,都 ...

  3. 一篇文章了解相见恨晚的 Android Binder 进程间通讯机制【转】

    本文转载自:https://blog.csdn.net/freekiteyu/article/details/70082302 Android-Binder进程间通讯机制 概述 最近在学习Binder ...

  4. android IPC 进程间通讯

    参考资料: http://blog.csdn.net/birdsaction/article/details/39451849 在这里我说一下学习技术的方法,别人的博客,别人的东西,再简单,自己没有写 ...

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

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

  6. 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 进程间 通讯 ...

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

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

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

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

  9. Android查缺补漏(IPC篇)-- 进程间通讯之Socket简介及示例

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

随机推荐

  1. C++学习(一):现代C++尝试

    C++是一门与时俱进的语言. 早期的C++关注的主要问题是通用性,却没有太多关注易用性的问题,使得C++成为了一门多范式语言,但是使用门槛较高. 从2011开始,C++的标准进行了较大的更新,开始更多 ...

  2. 转:C#制作ORM映射学习笔记二 配置类及Sql语句生成类

    在正式开始实现ORM之前还有一点准备工作需要完成,第一是实现一个配置类,这个很简单的就是通过静态变量来保存数据库的一些连接信息,等同于.net项目中的web.config的功能:第二需要设计实现一个s ...

  3. LeetCode OJ-- 3Sum Closest

    https://oj.leetcode.com/problems/3sum-closest/ 给一列数和target,在这一列数中找出3个数,使其和最接近target,返回这个target. 一般思路 ...

  4. JMeter常见四种变量简介

    在JMeter自动化测试脚本编写过程中,经常需要对测试脚本进行一些参数设置.例如,设置测试计划的全局变量(方便切换不同的测试环境).样本线程(HTTP请求等)的参数传递等. 通常,JMeter中常用的 ...

  5. [LOJ6235]区间素数个数

    题目大意: 给定$n(n\leq10^{11})$,求$\pi(n)$. 思路: 计算$\pi$函数有$O(n^{\frac23})$的Lehmer算法,这里考虑$O(\frac{n^{\frac34 ...

  6. XSY 1749 tree

    题目大意 给定一棵基环树, 问你有多少条路径的长度\(\ge K\). 点数\(\le 10^5\) Solution 基环树分治模板题. 我是这样做的: 加边的时候用并查集维护点的连通性, 少加入环 ...

  7. Qt小结

    (1)#include 报错fatal error: QHostInfo:No such file or directory, 解决办法 在.pro文件中添加 QT += core gui netwo ...

  8. sublime text常用快捷键(转)

    选择一个选中项的下一个匹配项: ctrl+d 把光标放在一个单词上,按下ctrl+ D,将选择这个单词.一直按住ctrl且按D多次,将选择当前选中项的下一个匹配项.通过按住ctrl,再按D三次,将选择 ...

  9. SAS学习笔记之函数应用

    今天在做数据需求的时候遇到一些问题,因为不能够在数据库里面做,仅仅好在SAS里面实现.这就遇到了一些麻烦,须要使用一些函数实现部分功能,如查找字段中某个特殊字符出现的次数,查找某个字符的位置等,以下一 ...

  10. js中推断浏览器类型

    在实际看发展.有时候会遇到在IOS和Android中要用不同的方法处理网页.须要让网页返回当前浏览器的类型. /** * 推断浏览器类型 */ var Browse = function () { / ...