Messenger学习记录

  Messenger的作用就是在不同进程中通过Message对象进行通信。Messenger 的创建直接new 就可以,其中构造方法有两个,一个是传入Handler 一个是传入IBinder ,传入Handler 是服务端接收消息用的构造方法,传入IBinder 是客户端用来发送消息的构造方法。我们可以从Messenger的两个构造方法中看出,Messenger 的内部实现和AIDL 是相同的,Messenger是基于AIDL 模式 实现的,Messenger 其实就是对AIDL 又进行一次封装。  

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

这个是服务端接收消息的构造方法。Handler.getIMessenger()方法直接回获取一个IMessenger 对象,这个方法里面是这样的

final IMessenger getIMessenger() {
    synchronized (mQueue) {
        if (mMessenger != null) {
            return mMessenger;
        }
        mMessenger = new MessengerImpl();
        return mMessenger;
    }
}可以出如果有mMessenger 直接返回,没有就创建一个MessengerImpl 实例类进行返回。 MessengerImpl  继承了IMessenger.Stub ,和AIDL 中的Stub一样。(内部的结构和AIDL 生成的一样,也有Proxy代理类)。
public Messenger(IBinder target) {
    mTarget = IMessenger.Stub.asInterface(target);
}

这个是客户端的构造方法,为什么要传递IBinder呢?这个IBinder 其实就是服务端的Messenger(内部实现的MessengerImpl),通过代理类去调用方法send 中的mRemote.transact(Stub.TRANSACTION_send, _data, null, // 接收的code和发送的code都是TRANSACTION_sendIBinder.FLAG_ONEWAY)方法和之前的AIDL 文件一模一样,没什么好说的,在transact 中调用ontransact 把数据传递到服务端,然后在ontransact 方法里面发送这个Message 到服务端的Handler内部中处理!。下面上服务端的代码

public class MessengerService extends Service {
    private final static String TAG = "MessengerService";


    @Override
    public IBinder onBind(Intent intent) {
        return messenger.getBinder();
    }

    private static class MessengerHandle extends Handler{

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case MyConstants.MSG_FROM_CLIENT:
                    Log.e(TAG,"receive msg from Client:" + msg.getData().getString("msg"));
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }
    private final Messenger messenger = new Messenger(new MessengerHandle());
}非常简单吧。只是内部比较麻烦而以。多想多思考就行了。

这个是客户端的

public class MainActivity extends AppCompatActivity {

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Messenger messenger = new Messenger(service);
            Message obtain = Message.obtain();
            Bundle bundle = new Bundle();
            bundle.putString("msg","Hello,this is Client");
            obtain.setData(bundle);
            try {
                messenger.send(obtain);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent intent = new Intent(this, MessengerService.class);
        bindService(intent,connection,BIND_AUTO_CREATE);
    }

    @Override
    protected void onDestroy() {
        unbindService(connection);
        super.onDestroy();
    }
} 注意了。客户端的 messenger.send(obtain); 这行代码和服务端的调用不是同一个方法哦!客户端的Messenger 是Proxy 的执行的是mRemote.transact核心代码。服务端的是Stub 里面的执行的是MessengerImpl 里面的Handler.this.sendMessage方法(MessengerImpl 是Handler的内部类)。 总结一下就是客户端通过把服务端的Binder 带到 自己的proxy 内部中作为全局变量保存起来。并且执行transact 方法,将data 客户端数据传递到服务端,服务端stub 中重写binder的onTransact方法接手到data, 进行解析创建message 将信息怎么来的,怎么存回去。最后通过Handler.this.sendMessage方法 发送到消息队列,服务端取出message.

在这里需要注意的是,我这篇博客写的阅读应用层Binder 和Messenger的具体内部代码,而且不是讲的原理,如果想要知道在什么时候客户端的Service 和服务端的ServiceManage 进行跨进程的连接,并且又如何映射的虚拟内存,在Binder 驱动层。那么我们就需要去从Context.BindService 方法中去进一步的查阅。不过,个人不推荐初学者尝试,有可能进去了走不出来,还浪费时间,还是希望大家多掌握一点基础知识 各种设计模式之后才去看这些比较复杂的结构源码。

 今天就分享这么多谢谢大家。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值