Android进程间通讯之messenger

来源:互联网 发布:网络代工 编辑:程序博客网 时间:2024/05/16 11:29

Android进程间通讯之messenger

http://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创建一个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 //服务端service13 public class MyService extends Service {14     private static final int CODE = 1;15     public MyService() {16     }17     @Override18     public IBinder onBind(Intent intent) {19         return mMessenger.getBinder();20     }21 22     //创建一个送信人,封装handler23     private Messenger mMessenger = new Messenger(new Handler() {24         @Override25         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     @Override24     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             @Override35             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         @Override52         public void onServiceConnected(ComponentName name, IBinder service) {53             //连接成功54             serverMessenger = new Messenger(service);55             Log.i("Main", "服务连接成功");56             mBond = true;57         }58 59         @Override60         public void onServiceDisconnected(ComponentName name) {61             serverMessenger = null;62             mBond = false;63         }64     }65     private Messenger mMessenger = new Messenger(new Handler(){66         @Override67         public void handleMessage(Message msg) {68             Toast.makeText(getApplicationContext(),msg.arg1+"",Toast.LENGTH_SHORT).show();69             super.handleMessage(msg);70         }71     });72     @Override73     protected void onDestroy() {74         if (mBond) {75             unbindService(conn);76         }77         super.onDestroy();78     }79 80 }
复制代码

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

0 0
原创粉丝点击