aidl用到的设计模式--Proxy代理模式
来源:互联网 发布:时间管理局 知乎 编辑:程序博客网 时间:2024/05/23 02:01
aidl用到的是远程代理模式,为客户端隐藏了IPC的细节。让客户端感觉好像拿到了一个服务器端对象的句柄。-------------------------------IGreetService.aidl-------------------------------这个aidl经过编译之后得到IGreetServcie.java
- package com.scott.aidl;
- import com.scott.aidl.Person;
- interface IGreetService {
- String greet(in Person person);
- }
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
- aidl用到的设计模式--Proxy代理模式
- aidl用到的设计模式--Proxy代理模式
- Proxy代理设计模式
- 设计模式 - 代理(Proxy)
- 代理设计模式--Proxy
- Proxy(代理)设计模式
- 代理 proxy 设计模式
- 设计模式----Proxy(代理)模式
- 设计模式--代理模式(Proxy)
- 设计模式 -- 代理模式(Proxy)
- 设计模式--代理模式(Proxy)
- [设计模式]Proxy代理模式
- 设计模式--Proxy(代理模式)
- [设计模式]代理模式(Proxy)
- 设计模式-Proxy代理模式
- 设计模式--proxy代理模式
- 设计模式 -- 代理模式 Proxy
- 设计模式-代理模式(Proxy)
- googleplay 付费(转)
- 日本作者Kardi Teknomo的网络教程
- Firefox 中文语言包安装方法
- 身份证前6位地区编码sql
- 如何日常保养电脑?
- aidl用到的设计模式--Proxy代理模式
- PhoneGap 06 PhoneGap Android平台配置
- 数据库迁移
- javaWeb测验
- 导出数据到EXCEL
- swing 中如何将CheckBox加入ComboBox
- 熊猫烧香病毒源码及分析
- Android之实现手势缩放imageview中的图片
- nginx+webpy+uswgi+jwplayer组合搭建流媒体服务器