AsyncChannel 的作用

  1. AsyncChannel 是两个不同的Handler 的传递消息通道,这两个Handler 有可能是在同一个进程,也有可能是在不同的进程,如果是在不同的进程则需要借助Binder 的IPC 机制进行通信。
  2.Messenger 与handler 相关联,Messenger 将消息发送给对应的Handler去处理,Messenger=new Messenger(handler),如果handler 来自其他进程,那么 handler 必须来自通过AIDL 转化的Service,Messagener=new Messenger(service),可以这么理解AsyncChannel,就是借助Messenger 机制,让不同的handler之间进行通信。
  3.AsyncChannel 提供客户端/服务端的通信模式,主要有两种应用场景
  <1> 服务端和客户端相互通信,服务端需要知道那些客户端向它发送请求,它收到客户端请求后,并和客户端建立连接,最后通过replyToMessage将反馈消息发送给客户端。可以连接为双向连接。以GsmDataConnectionTracker 所在的Handler  和 DataConnection 所在Handler  的通信为例。
   GsmDataConnectionTracker 利用DataConnectionAc(AsyncChannel的派生类),向DataConnection 发送请求,建立通信通道。
   int status = dcac.fullyConnectSync(mPhone.getContext(), this, conn.getHandler());
   status 表示通信通道是否建立成功,如果成功,就可以相互发送具体的消息了。
   fullyConnectSync 建立的是进程内的Handler 通信,首先初始化与连接相关的对象,如srcMessenger,DestMessager,对于同一进程的handler 通信,如果与连接相关的对象初始化完成了,那就说明双方的连接是没有问题了,只需要及建立通信通道。
   public int fullyConnectSync(Context srcContext, Handler srcHandler, Handler dstHandler) {
        int status = connectSync(srcContext, srcHandler, dstHandler);
        if (status == STATUS_SUCCESSFUL) {
            Message response = sendMessageSynchronously(CMD_CHANNEL_FULL_CONNECTION);
            status = response.arg1;
        }
        return status;
    }
    public int connectSync(Context srcContext, Handler srcHandler, Handler dstHandler) {
        return connectSync(srcContext, srcHandler, new Messenger(dstHandler));
    }
    public int connectSync(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
        if (DBG) log("halfConnectSync srcHandler to the dstMessenger  E");

        // We are connected
        connected(srcContext, srcHandler, dstMessenger);

        if (DBG) log("halfConnectSync srcHandler to the dstMessenger X");
        return STATUS_SUCCESSFUL;
    }
    public void connected(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
        if (DBG) log("connected srcHandler to the dstMessenger  E");

        // Initialize source fields
        mSrcContext = srcContext;
        mSrcHandler = srcHandler;
        mSrcMessenger = new Messenger(mSrcHandler);

        // Initialize destination fields
        mDstMessenger = dstMessenger;

        if (DBG) log("connected srcHandler to the dstMessenger X");
    }
   如果初始化成功就发送 CMD_CHANNEL_FULL_CONNECTION,的消息,这个消息被发送到 AsyncChannel 中的 SyncMessenger,SyncMessenger(同步Messenger) 维护着一个消息栈和消息发送线程(HandlerThread)。
    private static Message sendMessageSynchronously(Messenger dstMessenger, Message msg) {
            SyncMessenger sm = SyncMessenger.obtain();
            try {
                if (dstMessenger != null && msg != null) {
                    msg.replyTo = sm.mMessenger;
                    synchronized (sm.mHandler.mLockObject) {
                        dstMessenger.send(msg);
                        sm.mHandler.mLockObject.wait();
                    }
                } else {
                    sm.mHandler.mResultMsg = null;
                }
            } catch (InterruptedException e) {
                sm.mHandler.mResultMsg = null;
            } catch (RemoteException e) {
                sm.mHandler.mResultMsg = null;
            }
            Message resultMsg = sm.mHandler.mResultMsg;
            sm.recycle();
            return resultMsg;
        }
   从以上代码可以看出 对于发送的消息的replyTo 变成了SynMessenger 的 messenger(与SysnMessenger 的HandlerThread的Handler)。也就是说GsmDataConnectionTracker的消息通过SyncMessenger 发送到DataConnection的Handler,GsmDataConnectionTracker通过DataConnectionAc所建立的Handler (srcMessenger),就没有起作用。GsmDataConnectionTracker通过DataConnectionAc所建立的DestMessenger(目的Handler)还是起作用的。
   DataConnection 在接收到 CMD_CHANNEL_FULL_CONNECTION,后,创建自己的AsyncChannle ,通过 AsyncChannle 与 GsmDataConnectionTracker的DataConnectionAc的SyncMessenger的HandlerThread的Handler 建立连接,然后向HanlderThread的Handler 发送CMD_CHANNEL_FULLY_CONNECTED消息,并说明通信通道建立成功,HandlerThread的Handler 收到这个消息后,将这个消息转换成SyncMessenger的 resultMessage,并将resultMessage 交给 GsmDataConnectionTracker,那么GsmDataConnectionTracker就直到通信通道是连接成功的,它就可以发送其他具体的数据消息了。
   DataConnection 的 DcDefaultState处理 CMD_CHANNEL_FULL_CONNECTION
   case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
                  if (mAc != null) {
                        if (VDBG) log("Disconnecting to previous connection mAc=" + mAc);
                        mAc.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
                                AsyncChannel.STATUS_FULL_CONNECTION_REFUSED_ALREADY_CONNECTED);
                    } else {
                        mAc = new AsyncChannel();
                        mAc.connected(null, getHandler(), msg.replyTo);
                        if (VDBG) log("DcDefaultState: FULL_CONNECTION reply connected");
                        mAc.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
                                AsyncChannel.STATUS_SUCCESSFUL, mId, "hi");
                    }
                    break;
                }
   
  SyncMessenger 处理消息
    @Override
            public void handleMessage(Message msg) {
                mResultMsg = Message.obtain();
                mResultMsg.copyFrom(msg);
                synchronized(mLockObject) {
                    mLockObject.notify();
                }
            }
  这个应用场景的模式就是客户端和服务端都持有AsyncChannel 对象,客户端通过自己的AsynChannel 和服务端的Handler 建立连接,并发送 CMD_CHANNEL_FULL_CONNECTION到自己的AsyncChannel 的SyncMessenger中,SyncMessenger 将消息转发到服务端的Handler,也就是说客户端向服务端发送消息是通过自己的AsyncChannel 的SyncMessenger 转发的。服务端收到消息后,首先通过自己的AsyncChannel 和客户端的SyncMessenger 建立连接,然后将反馈消息,发送给SyncMessenger,由SynMessenger 转发给客户端。
  当然以上描述只说明了利用AsyncChannel 建立通信通道的过程,发送具体的消息的过程也是和上面描述的一样。
  <2> 服务端和客户端相互通信,服务端不需要知道哪些客户端向它发送请求,它只需要去处理客户端发送过来的消息,不许要和客户端建立连接,可以理解为单向连接。现在以MobileDataStateTracker所在的Handler 和 DataConnectionTracker 所在Handler 进行通信为例来进行说明。
    GsmDataConnectionTracker 的构造函数中,会发送一个 广播。
     protected void broadcastMessenger() {
        Intent intent = new Intent(ACTION_DATA_CONNECTION_TRACKER_MESSENGER);
        intent.putExtra(EXTRA_MESSENGER, new Messenger(this));
        mPhone.getContext().sendBroadcast(intent);
    }
    这个广播会被 MobileDataStateTracker 所接收。
    else if (intent.getAction().
                    equals(DataConnectionTracker.ACTION_DATA_CONNECTION_TRACKER_MESSENGER)) {
                if (VDBG) log(mApnType + " got ACTION_DATA_CONNECTION_TRACKER_MESSENGER");
                mMessenger = intent.getParcelableExtra(DataConnectionTracker.EXTRA_MESSENGER);
                AsyncChannel ac = new AsyncChannel();
                ac.connect(mContext, MobileDataStateTracker.this.mHandler, mMessenger);
   从代码中可以看出,初始化了一个 AsyncChannel ,将 MobileDataStateTracker 的Handler 和 DataConnectionTracker所在的Handler 连接起来。
    public void connect(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
        if (DBG) log("connect srcHandler to the dstMessenger  E");

        // We are connected
        connected(srcContext, srcHandler, dstMessenger);

        // Tell source we are half connected
        replyHalfConnected(STATUS_SUCCESSFUL);

        if (DBG) log("connect srcHandler to the dstMessenger X");
    }
     private void replyHalfConnected(int status) {
        Message msg = mSrcHandler.obtainMessage(CMD_CHANNEL_HALF_CONNECTED);
        msg.arg1 = status;
        msg.obj = this;
        msg.replyTo = mDstMessenger;
        mSrcHandler.sendMessage(msg);
    }
   与连接相关的对象初始化完成后, MobileDataStateTracker就收到了 MD_CHANNEL_HALF_CONNECTED,信息,并且处理。代码中的 mSrcHandler就是 MobileDataStateTracker
所在的Handler.
    public void handleMessage(Message msg) {
            switch (msg.what) {
                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
                    if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
                        if (VDBG) {
                            mMdst.log("MdstHandler connected");
                        }
                        mMdst.mDataConnectionTrackerAc = (AsyncChannel) msg.obj;
                    } else {
                        if (VDBG) {
                            mMdst.log("MdstHandler %s NOT connected error=" + msg.arg1);
                        }
                    }
                    break;
                case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
                    if (VDBG) mMdst.log("Disconnected from DataStateTracker");
                    mMdst.mDataConnectionTrackerAc = null;
                    break;
                default: {
                    if (VDBG) mMdst.log("Ignorning unknown message=" + msg);
                    break;
                }
            }
    这样。 mDataConnectionTrackerAc ,就被初始化为,已经建立了连接的AsyncChannel 对象,两个Handler 的通信通道建立了(AsyncChannel对象建立)。当 MobileDataStateTracker执行setUserDataEnable的时候。
     public void setUserDataEnable(boolean enabled) {
        if (DBG) log("setUserDataEnable: E enabled=" + enabled);
        final AsyncChannel channel = mDataConnectionTrackerAc;
        if (channel != null) {
            channel.sendMessage(CMD_SET_USER_DATA_ENABLE, enabled ? ENABLED : DISABLED);
            mUserDataEnabled = enabled;
        }
        if (VDBG) log("setUserDataEnable: X enabled=" + enabled);
     }
     这个channel 就是刚才 连接完成后获得的 mDataConnectionTrackerAc ,于是马上向 DataConnectionTracker 发送 CMD_SET_USER_DATA_ENABLE的请求,
     之前 AsyncChannel 的 mDstMessenger 已经初始化了,消息会直接发送给 DataConnectionTracker,DataConnectionTracker没有给MobileDataStateTracker任何反馈信息,直接处理了该消息。
   以上两个应用场景都是用同一个进程内的连个Handler 来说明的。简单地说,两个Handler通信(想象成服务端和客户端)的初始化工作包括两方面
   <1> 初始化连接对象,如mSrcMessenger,mDestmessenger,msrcHandler 等,如果这些初始化没有问题,说明 两个Handler 之间的连接没有问题。
   <2> 建立通信通道,建立通道的消息被服务端handler 处理后,就像客户端的Handler 发送消息,说明连接状态是成功的,比如发送 CMD_CHANNEL_FULL_CONNECTION,MD_CHANNEL_HALF_CONNECTED等消息,让客户端知道通信通道是否已经建立成功。
   如果 客户端的handler 不想同服务端的handler 进行通信了,那么就发送中断连接的消息。
   对于两个不同进程的Handler 进行通信,在进行连接的时候,需要借助Binder 的AIDL机制绑定远程的Service,如
   public int connectSrcHandlerToPackageSync(
            Context srcContext, Handler srcHandler, String dstPackageName, String dstClassName) {
        if (DBG) log("connect srcHandler to dst Package & class E");

        mConnection = new AsyncChannelConnection();

        /* Initialize the source information */
        mSrcContext = srcContext;
        mSrcHandler = srcHandler;
        mSrcMessenger = new Messenger(srcHandler);

        /*
         * Initialize destination information to null they will
         * be initialized when the AsyncChannelConnection#onServiceConnected
         * is called
         */
        mDstMessenger = null;

        /* Send intent to create the connection */
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.setClassName(dstPackageName, dstClassName);
        boolean result = srcContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
        if (DBG) log("connect srcHandler to dst Package & class X result=" + result);
        return result ? STATUS_SUCCESSFUL : STATUS_BINDING_UNSUCCESSFUL;
    }

   
 

你可能感兴趣的:(AsyncChannel 的作用)