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


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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值