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

本文解析了AIDL的工作原理及远程代理模式的应用,详细介绍了IGreetService.aidl文件的编译过程与生成的Java类结构,揭示了客户端与服务端通过代理对象进行进程间通信的机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. aidl用到的是远程代理模式,为客户端隐藏了IPC的细节。让客户端感觉好像拿到了一个服务器端对象的句柄。  
  2.   
  3. -------------------------------  
  4. IGreetService.aidl  
  5. -------------------------------  
  6. <ol class="dp-j" start="1"><li class="alt"><span><span class="keyword">package</span><span> com.scott.aidl;  </span></span></li><li><span><span class="keyword">import</span><span> com.scott.aidl.Person;  </span></span></li><li class="alt"><span>  </span></li><li><span><span class="keyword">interface</span><span> IGreetService {  </span></span></li><li class="alt"><span>    String greet(in Person person);  </span></li><li><span>}     
  7. </span></li></ol>  
这个aidl经过编译之后得到IGreetServcie.java


[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package com.scott.aidl;    
  2.     
  3. public interface IGreetService extends android.os.IInterface {    
  4.     /** Local-side IPC implementation stub class. */    
  5.     public static abstract class Stub extends android.os.Binder implements com.scott.aidl.IGreetService {    
  6.         private static final java.lang.String DESCRIPTOR = "com.scott.aidl.IGreetService";    
  7.     
  8.         /** Construct the stub at attach it to the interface. */    
  9.         public Stub() {    
  10.             this.attachInterface(this, DESCRIPTOR);    
  11.         }    
  12.     
  13.         /**  
  14.          * Cast an IBinder object into an com.scott.aidl.IGreetService  
  15.          * interface, generating a proxy if needed.  
  16.          */    
  17.         public static com.scott.aidl.IGreetService asInterface(android.os.IBinder obj) {    
  18.             if ((obj == null)) {    
  19.                 return null;    
  20.             }    
  21.             android.os.IInterface iin = (android.os.IInterface) obj.queryLocalInterface(DESCRIPTOR);    
  22.             if (((iin != null) && (iin instanceof com.scott.aidl.IGreetService))) {    
  23.                 return ((com.scott.aidl.IGreetService) iin);    
  24.             }    
  25.             return new com.scott.aidl.IGreetService.Stub.Proxy(obj);    
  26.         }    
  27.     
  28.         public android.os.IBinder asBinder() {    
  29.             return this;    
  30.         }    
  31.     
  32.         @Override    
  33.         public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)    
  34.                 throws android.os.RemoteException {    
  35.             switch (code) {    
  36.             case INTERFACE_TRANSACTION: {    
  37.                 reply.writeString(DESCRIPTOR);    
  38.                 return true;    
  39.             }    
  40.             case TRANSACTION_greet: {    
  41.                 data.enforceInterface(DESCRIPTOR);    
  42.                 com.scott.aidl.Person _arg0;    
  43.                 if ((0 != data.readInt())) {    
  44.                     _arg0 = com.scott.aidl.Person.CREATOR.createFromParcel(data);    
  45.                 } else {    
  46.                     _arg0 = null;    
  47.                 }    
  48.                 java.lang.String _result = this.greet(_arg0);    
  49.                 reply.writeNoException();    
  50.                 reply.writeString(_result);    
  51.                 return true;    
  52.             }    
  53.             }    
  54.             return super.onTransact(code, data, reply, flags);    
  55.         }    
  56.     
  57.         private static class Proxy implements com.scott.aidl.IGreetService {    
  58.             private android.os.IBinder mRemote;    
  59.     
  60.             Proxy(android.os.IBinder remote) {    
  61.                 mRemote = remote;    
  62.             }    
  63.     
  64.             public android.os.IBinder asBinder() {    
  65.                 return mRemote;    
  66.             }    
  67.     
  68.             public java.lang.String getInterfaceDescriptor() {    
  69.                 return DESCRIPTOR;    
  70.             }    
  71.     
  72.             public java.lang.String greet(com.scott.aidl.Person person) throws android.os.RemoteException {    
  73.                 android.os.Parcel _data = android.os.Parcel.obtain();    
  74.                 android.os.Parcel _reply = android.os.Parcel.obtain();    
  75.                 java.lang.String _result;    
  76.                 try {    
  77.                     _data.writeInterfaceToken(DESCRIPTOR);    
  78.                     if ((person != null)) {    
  79.                         _data.writeInt(1);    
  80.                         person.writeToParcel(_data, 0);    
  81.                     } else {    
  82.                         _data.writeInt(0);    
  83.                     }    
  84.                     mRemote.transact(Stub.TRANSACTION_greet, _data, _reply, 0);    
  85.                     _reply.readException();    
  86.                     _result = _reply.readString();    
  87.                 } finally {    
  88.                     _reply.recycle();    
  89.                     _data.recycle();    
  90.                 }    
  91.                 return _result;    
  92.             }    
  93.         }    
  94.     
  95.         static final int TRANSACTION_greet = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);    
  96.     }    
  97.     
  98.     public java.lang.String greet(com.scott.aidl.Person person) throws android.os.RemoteException;    
  99. }    

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

首先看第一个Interface的申明:

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

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

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


于是第二个类出现了

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


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

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public android.os.IBinder asBinder() {    
  2.      return mRemote;    
  3.  }    

mRemote是从哪儿来的?

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. private android.os.IBinder mRemote;    
  2.   
  3. Proxy(android.os.IBinder remote) {    
  4.     mRemote = remote;    
  5. }    

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

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public static com.scott.aidl.IGreetService asInterface(android.os.IBinder obj) {    
  2.     if ((obj == null)) {    
  3.         return null;    
  4.     }    
  5.     android.os.IInterface iin = (android.os.IInterface) obj.queryLocalInterface(DESCRIPTOR);    
  6.     if (((iin != null) && (iin instanceof com.scott.aidl.IGreetService))) {    
  7.         return ((com.scott.aidl.IGreetService) iin);    
  8.     }    
  9.     return new com.scott.aidl.IGreetService.Stub.Proxy(obj);    
  10. }    

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

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 这些相关的接口和类吧。


转载:http://blog.youkuaiyun.com/safsasasa/article/details/18085871

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值