Messenger 麻烦了解一下

前言

搞网络管理 ConnectivityService 的时候发现里面用了很多Asynchannel。查了一下看了一下源码发现它是messenger封装的,而messenger又是基于aidl 的,所以这里在写Asynchannel 之前用一篇文章来介绍一下Messenger 。

Messenger 与AIDL 的区别

1、Messenger适合传递数据少,数据量小的情况,直接发送message或者携带bundle,AIDL适合数据多,数据量大的情况
2、Messenger 是异步的,因为它在实现的时候源码里面AIDL 接口的类型是oneway 参数。

Messenger 的原理分析

public Messenger(Handler target) {
        mTarget = target.getIMessenger();
    }

1、构造函数里面需要传入一个Handler,handler 的getIMessenger() 实际上是通过 MessengerImpl 获取messenger 的对象。
MessengerImpl 继承 IMessenger.Stub类,是messenger binder 跨进程的服务端。

    final IMessenger getIMessenger() {
        synchronized (mQueue) {
            if (mMessenger != null) {
                return mMessenger;
            }
            mMessenger = new MessengerImpl();
            return mMessenger;
        }
    }

    private final class MessengerImpl extends IMessenger.Stub {
        public void send(Message msg) {
            msg.sendingUid = Binder.getCallingUid();
            Handler.this.sendMessage(msg);
        }
    }

2、在Messenger 的客户端可以通过IBinder 接口获取服务端的messenger。

    /**
     * Create a Messenger from a raw IBinder, which had previously been
     * retrieved with {@link #getBinder}.
     * 
     * @param target The IBinder this Messenger should communicate with.
     */
    public Messenger(IBinder target) {
        mTarget = IMessenger.Stub.asInterface(target);
    }

3、发送message 消息 ,可以在message里面携带Bundle信息

  /**
     * Send a Message to this Messenger's Handler.
     * 
     * @param message The Message to send.  Usually retrieved through
     * {@link Message#obtain() Message.obtain()}.
     * 
     * @throws RemoteException Throws DeadObjectException if the target
     * Handler no longer exists.
     */
    public void send(Message message) throws RemoteException {
        mTarget.send(message);
    }

4.流程图

这里盗一张图充个门面。其中补充一下Messenger 的binder 跨进程实现是 IMessenger.Stub.asInterface 为客户端,服务端是 extends IMessenger.Stub 的类,比如 Handler 里面 MessengerImpl 就是messenger 的服务端实现类。
在这里插入图片描述

Messenger 的使用可以是单向的客户端向服务端发送消息,也可以是服务端收到客户端消息后message.replyTo.send(replyMsg) 回复消息,message的replyTo 实际上 是获取了一个messenger对象。这里是客户端 发消息的message通过replyTo 参数里面传一个 messenger 对象尽量msg.replyTo = clientMessenger就会获取到服务端发送过来的Messenger 对象。

重点说完了,贴一个demo 源码吧 。。。

客户端:

package com.tsp.asyncchanneldemo.messenger;

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.Looper;
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 androidx.appcompat.app.AppCompatActivity;

import com.tsp.asyncchanneldemo.R;

public class MessengerClientActivity extends AppCompatActivity {
    private static final String TAG=MessengerClientActivity.class.getSimpleName();

    private Button mButton;
    public static final int FROM_SERVER = 1;

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

        //启动服务
        startService();

        //绑定服务
        bindService();

        mButton = (Button) findViewById(R.id.button);
        mButton.setEnabled(false);
        //点击按键后,利用Messenger向Service发送消息
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mMessenger != null) {
                    try {
                        Message msg = Message.obtain();
                        msg.what = 1;
                        Bundle data = new Bundle();
                        data.putString("msg", "I am from the client.");
                        msg.setData(data);

                        //message replyto from server
                        msg.replyTo = clientMessenger;
                        mMessenger.send(msg);
                    } catch (RemoteException e) {
                    }
                }
            }
        });
    }

    //client messenger handler
    private Handler handler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case FROM_SERVER:
                    Log.d(TAG,"get msg from server");
                    Log.e(TAG, msg.getData().getString("reply"));
                    break;
                default:
                    break;
            }
        }
    };


    private Messenger clientMessenger = new Messenger(handler);

    @Override
    public void onDestroy() {
        super.onDestroy();
        unBindService();
        stopService();
    }

    private Intent mIntent;

    private void startService() {
        mIntent = new Intent(this, MessengerService.class);
        this.startService(mIntent);
    }

    private ServiceConnection mServiceConnection;

    private void bindService() {
        mServiceConnection = new LocalServiceConnection();
        this.bindService(mIntent, mServiceConnection, BIND_AUTO_CREATE);
    }

    Messenger mMessenger;

    private class LocalServiceConnection implements android.content.ServiceConnection {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //绑定服务后,获得Messenger并激活Button
            mMessenger = new Messenger(service);
            mButton.setEnabled(true);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mButton.setEnabled(false);
        }
    }

    private void stopService() {
        stopService(mIntent);
    }

    private void unBindService() {
        unbindService(mServiceConnection);
    }
}

服务端:

package com.tsp.asyncchanneldemo.messenger;

import android.app.Service;
import android.content.Intent;
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 androidx.annotation.Nullable;

public class MessengerService extends Service {

    private static final String TAG = "MessengerService";

    /**
     * 处理来自客户端的消息,并用于构建Messenger
     */
    private static class MessengerHandler extends Handler {
        @Override
        public void handleMessage(Message message) {
            switch (message.what) {
                case 1:
                    Log.e(TAG, "receive message from client:" + message.getData().getString("msg"));

                    //回复消息给客户端
                    Message replyMsg = Message.obtain();
                    replyMsg.what = 1;
                    Bundle bundle = new Bundle();
                    bundle.putString("reply", "听到你的消息了,请说点正经的");
                    replyMsg.setData(bundle);
                    try {
                        message.replyTo.send(replyMsg);     //回信
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                    break;
                default:
                    super.handleMessage(message);
                    break;
            }
        }
    }

    /**
     * 构建Messenger对象
     */
    private final Messenger mMessenger = new Messenger(new MessengerHandler());

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG,"onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        //将Messenger对象的Binder返回给客户端
        return mMessenger.getBinder();
    }
}

AndroidManifest 文件里面服务端加上 process 属性

android:process=":remote"

写到这里就O 了,大概就是这样吧,下一篇写Asychannel。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mrsongs的心情杂货铺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值