aidl用到的设计模式--Proxy代理模式

来源:互联网 发布:时间管理局 知乎 编辑:程序博客网 时间:2024/05/23 02:01

aidl用到的是远程代理模式,为客户端隐藏了IPC的细节。让客户端感觉好像拿到了一个服务器端对象的句柄。-------------------------------IGreetService.aidl-------------------------------
  1. package com.scott.aidl;  
  2. import com.scott.aidl.Person;  
  3.   
  4. interface IGreetService {  
  5.     String greet(in Person person);  
  6. }  
这个aidl经过编译之后得到IGreetServcie.java


    package com.scott.aidl;            public interface IGreetService extends android.os.IInterface {          /** Local-side IPC implementation stub class. */          public static abstract class Stub extends android.os.Binder implements com.scott.aidl.IGreetService {              private static final java.lang.String DESCRIPTOR = "com.scott.aidl.IGreetService";                    /** Construct the stub at attach it to the interface. */              public Stub() {                  this.attachInterface(this, DESCRIPTOR);              }                    /**              * Cast an IBinder object into an com.scott.aidl.IGreetService              * interface, generating a proxy if needed.              */              public static com.scott.aidl.IGreetService 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 com.scott.aidl.IGreetService))) {                      return ((com.scott.aidl.IGreetService) iin);                  }                  return new com.scott.aidl.IGreetService.Stub.Proxy(obj);              }                    public android.os.IBinder asBinder() {                  return this;              }                    @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_greet: {                      data.enforceInterface(DESCRIPTOR);                      com.scott.aidl.Person _arg0;                      if ((0 != data.readInt())) {                          _arg0 = com.scott.aidl.Person.CREATOR.createFromParcel(data);                      } else {                          _arg0 = null;                      }                      java.lang.String _result = this.greet(_arg0);                      reply.writeNoException();                      reply.writeString(_result);                      return true;                  }                  }                  return super.onTransact(code, data, reply, flags);              }                    private static class Proxy implements com.scott.aidl.IGreetService {                  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 java.lang.String greet(com.scott.aidl.Person person) throws android.os.RemoteException {                      android.os.Parcel _data = android.os.Parcel.obtain();                      android.os.Parcel _reply = android.os.Parcel.obtain();                      java.lang.String _result;                      try {                          _data.writeInterfaceToken(DESCRIPTOR);                          if ((person != null)) {                              _data.writeInt(1);                              person.writeToParcel(_data, 0);                          } else {                              _data.writeInt(0);                          }                          mRemote.transact(Stub.TRANSACTION_greet, _data, _reply, 0);                          _reply.readException();                          _result = _reply.readString();                      } finally {                          _reply.recycle();                          _data.recycle();                      }                      return _result;                  }              }                    static final int TRANSACTION_greet = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);          }                public java.lang.String greet(com.scott.aidl.Person person) throws android.os.RemoteException;      }  

这里面一共定义了三个class.

首先看第一个Interface的申明:

public interface IGreetService extends android.os.IInterface {
这个Interface继承了 android.os.IInterface

 1 /*  2  * Copyright (C) 2006 The Android Open Source Project  3  *  4  * Licensed under the Apache License, Version 2.0 (the "License");  5  * you may not use this file except in compliance with the License.  6  * You may obtain a copy of the License at  7  *  8  *      http://www.apache.org/licenses/LICENSE-2.0  9  * 10  * Unless required by applicable law or agreed to in writing, software 11  * distributed under the License is distributed on an "AS IS" BASIS, 12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13  * See the License for the specific language governing permissions and 14  * limitations under the License.                                                                                                                                                                                15  */ 16  17 package android.os; 18  19 /** 20  * Base class for Binder interfaces.  When defining a new interface, 21  * you must derive it from IInterface. 22  */ 23 public interface IInterface 24 { 25     /** 26      * Retrieve the Binder object associated with this interface. 27      * You must use this instead of a plain cast, so that proxy objects 28      * can return the correct result. 29      */ 30     public IBinder asBinder(); 31 }

就是一个类型转换,注释里面说是要用这个函数的转换而不是强制类型转换,从而让代理对象可以返回一个正确的值。那就看一下代理对象是如何实现这个函数的。


于是第二个类出现了

private static class Proxy implements com.scott.aidl.IGreetService {


这个类实现了上述接口,并且是一个私有的静态内部类。他实现IInterface中的asBinder方法如下:

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

mRemote是从哪儿来的?

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

原理是从构造函数传过来的。那代理对象是在哪里构造的?

        public static com.scott.aidl.IGreetService 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 com.scott.aidl.IGreetService))) {                  return ((com.scott.aidl.IGreetService) iin);              }              return new com.scott.aidl.IGreetService.Stub.Proxy(obj);          }  

这是在另外一个内部类里面的,这个类的声明如下:

public static abstract class Stub extends android.os.Binder implements com.scott.aidl.IGreetService {

这个类继承了Binder,并且实现了之前的那个人service,跟上面那个类一样的。之前那个类是私有的,这个是共有的而且还是抽象的。

刚好这里面有个函数asInterface。这说明Binder需要把自己转化成一个Interface给别人用。而Interface需要把自己转化为Binder给别人用。真是一对好机油啊。

因为客户端需要的是一个Interface的句柄,所以这里提供了这个函数。客户端是这样调用的

IGreetService remoteService = IGreetService.Stub.asInterface(binder); 这个binder是系统回调 service的 onConnection的时候传过来的。

这段代码大概意思就是说如果service是一个本地对象就可以直接拿到service对象的句柄,否则我们就通过remote proxy的方式拿到一个代理对象。由这个代理对象在背后

默默的为我们工作,默默的处理进程间通讯的问题。



这里面比较绕的是内部类跟外部类的关系比较复杂。不止是内外的关系,内部类又继承了外部类,而且继承的层次还不只一层,有两层嵌套。而且还巧妙的运用了proxy的

设计模式。有趣的是这段代码是自动生成的,我们只需要定义Aidl文件,编译器会自动帮我们生成这段代码。值得看一下!后面再看一下IBinder Binder, Service ServiceConnection 这些相关的接口和类吧。



参考了android源码,和一篇博客,附上地址http://blog.csdn.net/liuhe688/article/details/6409708


0 0