Messenger是怎样实现单线程的

Messenger是实现进程通讯的一个工具,只不过它是单线程实现的那么他是怎么实现单线程的呢?

这里有一个例子:Android 基于Message的进程间通信 Messenger完全解析 通信实例

看一下服务端service中的代码:

public class MessengerService extends Service {
    private static final int MSG_SUM = 0x110;

    private Messenger mMessenger = new Messenger(new Handler() {
        @Override
        public void handleMessage(Message msg) {
            Message message = Message.obtain(msg);
            switch (msg.what) {
                case MSG_SUM:
                    msg.what = MSG_SUM;
                    try {
                        Thread.sleep(2000);
                        message.arg2 = msg.arg1 + msg.arg2;
                        msg.replyTo.send(message);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                    break;
            }
            super.handleMessage(msg);
        }
    });

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

比较简单,只是实现了一个Messenger,并在onBind()中返回mMessenger中的binder。

那么我们来看一下Messenger的构造方法。

private final IMessenger mTarget;

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

这个构造方法就是将Handler中的IMessenger对象取出来赋值给自己的mTarget。

那么我们再看一下getIMessenger()方法:

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);
    }
}

这里就有一个类IMessenger,他就是ALDL生成的一个类,前面Binder应用层架构–AIDL从自动生成到手动编写 已经讲过。方法send是IMessenger里定义的抽象方法(比较重要,下面会讲)。这里实现的是Handler将Message插入队列MessageQueue。这就是Messenger的一个构造方法。

mMessenger.getBinder()呢?

public IBinder getBinder() {
    return mTarget.asBinder();
}

这里返回的是IMessenger的asBinder方法,然后在IMessenger中找到源码:

public android.os.IBinder asBinder() {
    return this;
}

这里返回的是IMessenger.Stub,它继承了Binder类和IMessenger接口。

然后我们看一下客户端的代码:

public class MainActivity extends AppCompatActivity {
    private static final int MSG_SUM = 0x110;
    private Button add;
    private Messenger mService;
    private boolean isConn = false;

    Messenger mMessemger = new Messenger(new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_SUM:
                    break;
            }
            super.handleMessage(msg);
        }
    });

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mService = new Messenger(service);
            isConn = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mService = null;
            isConn = false;
        }
    };

    private int value;

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

        add = (Button) findViewById(R.id.add);

        bind();


        add.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int a = value++;
                int b = (int) (Math.random() * 100);
                Message message = Message.obtain(null, MSG_SUM, a, b);
                message.replyTo = mMessemger;
                if(isConn){
                    try {
                        mService.send(message);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    private void bind() {
        Intent intent = new Intent();
        intent.setAction("com.demo.ln.service");
        bindService(intent, connection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(connection);
    }
}

这里我们就按照操作顺序来捋一下。

当向服务端发送消息时,会初始化一个消息,这个消息会携带Messenger即message.replyTo = mMessemger;那么mMessemger是怎么来的,我们来看一下源码:

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

也是通过Handler获得的,也就是说Handler中会新建一个Messenger,并将它赋值给msg。

然后Messenger向服务端发送消息mService.send(message);mService也是一个Messenger类,它是怎么来的呢? 代码中是这样写的mService = new Messenger(service);我们看一下源码:

public Messenger(IBinder target) {
    mTarget = IMessenger.Stub.asInterface(target);
}

再来看一下,IMessenger.Stub.asInterface的源码:

public static android.os.IMessenger asInterface(android.os.IBinder obj) {
        if ((obj == null)) {
            return null;
        }
        android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
        if (((iin != null) && (iin instanceof android.os.IMessenger))) {
            return ((android.os.IMessenger) iin);
        }
        return new android.os.IMessenger.Stub.Proxy(obj);
}

Proxy:

private static class Proxy implements android.os.IMessenger {
      private android.os.IBinder mRemote;


      Proxy(android.os.IBinder remote) {
          mRemote = remote;
      }


      public android.os.IBinder asBinder() {
          return mRemote;
      }


      public java.lang.String getInterfaceDescriptor() {
          return DESCRIPTOR;
      }


      public void send(android.os.Message msg)throws android.os.RemoteException {
          android.os.Parcel _data = android.os.Parcel.obtain();
          try {
              _data.writeInterfaceToken(DESCRIPTOR);
              if ((msg != null)) {
                  _data.writeInt(1);
                  msg.writeToParcel(_data, 0);// 将msg所有字段(what,obj)写到_data中去
              } else {
                  _data.writeInt(0);
              }
              mRemote.transact(Stub.TRANSACTION_send, _data, null,
// // 接收的code和发送的code都是TRANSACTION_send
                      android.os.IBinder.FLAG_ONEWAY);
          } finally {
              _data.recycle();
          }
      }
}

现在找到根了,mService 其实就是Proxy的一个实例,mService.send(message)执行的就是Proxy类的send方法,msg.writeToParcel(_data, 0)将msg所有字段(what,obj)写到_data中去,这就是ALDL的向服务端传msg。writeToParcel()方法的源码:

public void writeToParcel(Parcel dest, int flags) {
        if (callback != null) {
            throw new RuntimeException(
                "Can't marshal callbacks across processes.");
        }
        dest.writeInt(what);
        dest.writeInt(arg1);
        dest.writeInt(arg2);
        if (obj != null) {
            try {
                Parcelable p = (Parcelable)obj;
                dest.writeInt(1);
                dest.writeParcelable(p, flags);
            } catch (ClassCastException e) {
                throw new RuntimeException(
                    "Can't marshal non-Parcelable objects across processes.");
            }
        } else {
            dest.writeInt(0);
        }
        dest.writeLong(when);
        dest.writeBundle(data);
        Messenger.writeMessengerOrNullToParcel(replyTo, dest);
        dest.writeInt(sendingUid);
    }

可以看出这个方法就是将msg拆开,一个一个的向服务端传过去。这就是ALDL向服务端传数据。

然后ALDL中IMessenger.Stub类的onTransact方法接收数据,来看一下IMessenger.Stub类中的onTransact方法:

@Override
public boolean onTransact(int code, android.os.Parcel data,android.os.Parcel reply, int flags)throws android.os.RemoteException {
    switch (code) {
        case INTERFACE_TRANSACTION: {
            reply.writeString(DESCRIPTOR);
            return true;
        }
        case TRANSACTION_send: {
// 接收的code和发送的code都是TRANSACTION_send
            data.enforceInterface(DESCRIPTOR);
            android.os.Message _arg0;
            if ((0 != data.readInt())) {
// data.readInt为1(当msg不为空时)
                _arg0 = android.os.Message.CREATOR.createFromParcel(data);
            } else {
                _arg0 = null;
            }
            this.send(_arg0);
            return true;
        }
    }
    return super.onTransact(code, data, reply, flags);
}

android.os.Message.CREATOR.createFromParcel(data)方法就是接收数据。接受完之后处理数据this.send(_arg0);这个this是哪一个呢?
在这里目前有三个IMessenger的对象,也就有三个send方法,一个是IMessenger.stub.Proxy对象 ,一个是客户端Handler里边的MessengerImpl对象,一个是服务端Handler里边的MessengerImpl对象,这个this指代的是IMessenger.stub对象,Proxy没有继承 IMessenger.stub,所以排除了。以为这时候已经把数据传到服务端进程,所以这个this指的是服务端Handler里边的MessengerImpl对象。MessengerImpl类的send源码:

public void send(Message msg) {
    msg.sendingUid = Binder.getCallingUid();
    Handler.this.sendMessage(msg);
}

看到这是不是很熟悉,不熟悉的看一下Handler通信机制 ,剩下的就是通过Handler进行数据的传递,放入MessageQueue队列之中,一个个的处理,最后在服务端service.Messenger的handleMessage中处理问题。

 public void handleMessage(Message msg) {
    Message message = Message.obtain(msg);
    switch (msg.what) {
        case MSG_SUM:
            msg.what = MSG_SUM;
            try {
                Thread.sleep(2000);
                message.arg2 = msg.arg1 + msg.arg2;
                msg.replyTo.send(message);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            break;
    }
    super.handleMessage(msg);
}

在这个方法中,msg.replyTo.send(message)向客户端返回信息。msg.replyTo就是message自带的Messenger,就是从客户端传过来的mService。

在这个过程中,一共用了三个Messenger,分别是mService,客户端的mMessenger,服务端的mMessenger。

这三个对象中只有mService是传递消息的,剩下的两个分别在自己所在的进程进行消息的接收和处理。这个地方描述的或许不准确,若有问题请告知。

参考资料:

Android 基于Message的进程间通信 Messenger完全解析

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值