android开发笔记之进程通信Messenger

写在前面的话

前面我写了一篇文章—android学习之remote service 的aidl详解,讲到跨进程多线程通信,我们使用aidl技术来实现。
但是平时我们大部分的应用可能只要要求跨进程通信,而不需要使用多线程,那么这时候,Messenger就是我们的一个非常好的选择。比起aidl来,Messenger实现更简单,并且不需要考虑线程安全的问题。

我参考了文章:
Android 基于Message的进程间通信 Messenger完全解析这里写链接内容

和官方文档:
android_sdk_docs_offline/guide/components/bound-services.html#Binding
大概弄明白了Messenger。

Messenger官方文档定义

Reference to a Handler, which others can use to send messages to it. This allows for the implementation of message-based communication across processes, by creating a Messenger pointing to a Handler in one process, and handing that Messenger to another process.

Messenger是基于消息的跨进程通信,Messenger要与Handler联合使用.
这个说的太抽象了,但是,我们可以看一下Messenger的几个关键方法:
二个构造方法:
Messenger(Handler target)
Create a new Messenger pointing to the given Handler.

Messenger(IBinder target)
Create a Messenger from a raw IBinder, which had previously been retrieved with getBinder().

发送消息的方法:
send(Message message)
Send a Message to this Messenger’s Handler.

Messenger实例

Server端:

MessengerService.java

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.util.Log;
import android.widget.Toast;

public class MessengerService extends Service {

    public static final String TAG = "MessengerService";

    public static final int MSG_SEND_TO_SERVER = 1;
    public static final int MSG__REPLY_FROM_SERVER = 2;

    final Messenger mMessenger = new Messenger(new IncomingHandler());

    class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_SEND_TO_SERVER:
                    Log.i(TAG, "MSG_SEND_TO_SERVER:"+"--msg.arg1:"+msg.arg1+"--msg.arg2:"+msg.arg2);
                    try {
                        Message messageReplyToClient = new Message();
                        messageReplyToClient.what = MSG__REPLY_FROM_SERVER;
                        messageReplyToClient.arg1 = msg.arg2;
                        messageReplyToClient.arg2 = msg.arg1;
                        msg.replyTo.send(messageReplyToClient);
                    } catch (RemoteException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }               
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
        return mMessenger.getBinder();
    }
}

大家会发现这个Server端的代码非常的简单,就是在onBind方法中返回一个mMessenger.getBinder()变量给client,并且定义一个Messenger mMessenger变量,mMessenger与IncomingHandler相关联,在handleMessage方法中处理client发送过来的信息。
我们在handleMessage方法可的主要操作是将client发送过来的Message的arg1和arg2值交换,再返回给client。
将消息返回给client端关键是要注意将要执行msg.replyTo的send方法:

msg.replyTo.send(messageReplyToClient);

在androidmanifest.xml中,我们定义service:

<service android:name=".MessengerService">  
  <intent-filter>  
    <action android:name="com.android.ACTION.MessengerService" />  
  </intent-filter>  
</service>  

Client端

MainActivity.java

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.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;

public class MainActivity extends Activity {

    public static final String TAG = "MainActivity";
    public static final int MSG_SEND_TO_SERVER = 1;
    public static final int MSG__REPLY_FROM_SERVER = 2;      
    private Messenger mMessenger;
    boolean mBound;
    private TextView textViewShowConnectState;
    private TextView textViewMessageSendToService;
    private TextView textViewMessageReceiverFromService;
    private Button button;

    private Messenger mMessengerReceive = new Messenger(new MyHandler());
    class MyHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG__REPLY_FROM_SERVER:
                    Log.i(TAG, "MSG__REPLY_FROM_SERVER:"+"--msg.arg1="+msg.arg1+"--msg.arg2="+msg.arg2);
                    textViewMessageReceiverFromService.setText("msg:server-->client:"+"--msg.arg1="+msg.arg1+"--msg.arg2="+msg.arg2);
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }

    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            mMessenger = new Messenger(service);
            mBound = true;
            textViewShowConnectState.setText("service connect");            
        }

        public void onServiceDisconnected(ComponentName className) {
            mMessenger = null;
            mBound = false;
            textViewShowConnectState.setText("service disconnect");
        }
    };

    public void sendMessage(View v) {
        if (!mBound) return;
        // Create and send a message to the service, using a supported 'what' value
        int arg1 = (int) (Math.random() * 100);;
        int arg2 = (int) (Math.random() * 100);;
        Message msg = Message.obtain(null, MSG_SEND_TO_SERVER, arg1, arg2);
        msg.replyTo = mMessengerReceive;
        textViewMessageSendToService.setText("msg:client-->server:"+"--msg.arg1="+msg.arg1+"--msg.arg2="+msg.arg2);
        try {
            mMessenger.send(msg);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
    }

    private void init() {
        // TODO Auto-generated method stub 
        textViewShowConnectState = (TextView)findViewById(R.id.textViewShowConnectState);
        textViewMessageSendToService = (TextView)findViewById(R.id.textViewMessageSendToService);
        textViewMessageReceiverFromService = (TextView)findViewById(R.id.textViewMessageReceiverFromService);
        button = (Button)findViewById(R.id.button);
    }

    @Override
    protected void onStart() {
        super.onStart();
        bindService(new Intent("com.android.ACTION.MessengerService"), mConnection,
            Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (mBound) {
            unbindService(mConnection);
            mBound = false;
        }
    }

}

我们Client给Server发送消息的是封装在sendMessage方法中的:

mMessenger.send(msg);

那么如何响应从server端回传的消息了,这中间的关键是把client发送到server的消息msg与回调处理的Messenger mMessengerReceive相关联:

msg.replyTo = mMessengerReceive;

布局文件:

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/textViewShowConnectState"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />

    <Button 
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/textViewShowConnectState"
        android:onClick="sendMessage"      
        android:text="click send message to Server"  
        />

    <TextView
        android:id="@+id/textViewMessageSendToService"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/button"/>

    <TextView
        android:id="@+id/textViewMessageReceiverFromService"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/textViewMessageSendToService"/>

</RelativeLayout>

效果图

从源码和效果图,我们可以看出,这个Demo是从Client发送一个消息到Server,Server把消息的msg.arg1和msg.arg2的值交换后再反馈给Client,Client将从Client发送到Server的消息和Server返回的消息都显示出来。

从这个Demo,我们也能非常明显的看出来,Messenger实现跨进程通信比aidl实现跨进程通信是更简单,更方便,条理也是更清晰。所以,如果实现跨进程非多线程的通信,我们推荐使用Messenger来实现。

你可能感兴趣的:(android,messenger)