当前位置:首页 > CN2资讯 > 正文内容

AndroidStudio已经关了代理还走代理

2天前CN2资讯


return true; } case TRANSACTION_testFun: { data.enforceInterface(descriptor); this.testFun(); reply.writeNoException(); return true; } default: { return super.onTransact(code, data, reply, flags); } } }// 主要关注代理模式的实现;可以看到AIDL的Proxy是通过静态代理模式实现 private static class Proxy implements com.bc.sample.IMyAidlInterface { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } @Override public android.os.IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } @Override public void testFun() throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); boolean _status = mRemote.transact(Stub.TRANSACTION_testFun, _data, _reply, 0); if (!_status && getDefaultImpl() != null) { getDefaultImpl().testFun(); return; } _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } public static com.bc.sample.IMyAidlInterface sDefaultImpl; } static final int TRANSACTION_testFun = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); public static boolean setDefaultImpl(com.bc.sample.IMyAidlInterface impl) { // Only one user of this interface can use this function // at a time. This is a heuristic to detect if two different // users in the same process use this function. if (Stub.Proxy.sDefaultImpl != null) { throw new IllegalStateException(“setDefaultImpl() called twice”); } if (impl != null) { Stub.Proxy.sDefaultImpl = impl; return true; } return false; } public static com.bc.sample.IMyAidlInterface getDefaultImpl() { return Stub.Proxy.sDefaultImpl; } } public void testFun() throws android.os.RemoteException; }

三、动态代理

在2.1的静态代理代码中,如果现在需要扩展一个新的接口,那就需要分别在接口层、实际处理类、代理类中分别改动,如下所示:

// 1.首先定义接口层 interface ILogSender { public void sendLog(String log); }// 2.定义实现类 public class MainLogSender implements ILogSender {@Override public void sendLog(String log) { Log.d(“LogSender”, “MainLogSender send” + log); } }// 3.定义代理类 public class LogSenderProxy implements ILogSender { // 代理类持有被代理类的引用 private ILogSender mainLogSender = new MainLogSender();@Override public void sendLog(String log) { // 代理类需要完成的一些额外处理 Log.d(“LogSender”, “ProxyLogSender” + log); String finalLog = Thread.currentThread() + log; mainLogSender.sendLog(finalLog); } }

当代理一个新的接口时可见,新的代理类与其他代理类代码是高度相似的,因此可以采用动态代理的方式来完成类似的功能。

3.1 基础用法

与静态代理不同,动态代理类的class是在运行过程中动态生成的。

3.1.1 基础用法

首先定义接口层:

// 定义接口层 interface ILogProcessor { public void printLog(String log); }

然后使用Proxy.newProxyInstance完成动态代理如下:

private void main() { ILogProcessor proxy = (ILogProcessor) Proxy.newProxyInstance(this.getClassLoader(), new Class<?>[] {ILogPrinter.class}, new InvocationHandler() {/** • @param proxy 代理对象 • @param method 被调用的方法 • @param args 被调用的方法的参数列表 */ @Override public Object invoke(Object proxy, Method method, Object[] args) { String log = (String)args[0]; Log.d(“LogProcessor”, “ProxyLogProcessor” + log); String finalLog = Thread.currentThread() + log; Log.d(“LogProcessor”, “printLog” + finalLog); return null; } });proxy.printLog(“”); }

其中,InvocationHandler就是将静态代理中需要实现的部分抽离了出来,即动态生成的Proxy代理了InvocationHandler。

3.1.2 动态生成的class

动态生成的代理类的方法实际调用都到了InvocationHandler的invoke方法,动态生成的代理类class伪代码如下:

public final class $Proxy0 extends Proxy implements ILogProcessor { static { m3 = Class.forName(“com.bc.sample.ILogProcessor”).getMethod(“printLog”); } private static Method m3; public void printLog(String log) { // 实际调用到了InvocationHandler的invoke方法 super.h.invoke(this, m3, (Object[])log); } }

3.1.3 源码分析

下面分析Proxy.newProxyInstance的源码:

public class Proxy implements java.io.Serializable { // 动态生成的class的缓存;ProxyClassFactory可动态生成代理class private static final WeakCache<ClassLoader, Class<?>[], Class<?>> proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());// 生成代理class并返回对应的实例 public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) { Objects.requireNonNull(h); final Class<?>[] intfs = interfaces.clone(); // 查找或动态生成代理类的class Class<?> cl = getProxyClass0(loader, intfs); // 获取动态代理类的构造函数 final Constructor<?> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; if (!Modifier.isPublic(cl.getModifiers())) { cons.setAccessible(true); } // 通过反射调用构造函数返回代理类的实例;参数中的InvocationHandler对象作为参数传递给类构造函数; return cons.newInstance(new Object[]{h}); }// 获取动态代理类class private static Class<?> getProxyClass0(ClassLoader loader, Class<?>… interfaces) { return proxyClassCache.get(loader, interfaces); }private static final class ProxyClassFactory implements BiFunction<ClassLoader, Class<?>[], Class<? { // prefix for all proxy class names private static final String proxyClassNamePrefix = “$Proxy”;// WeakCache.get()会调用到apply,最终调用generateProxy生成动态代理类class @Override public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) { // … return generateProxy(proxyName, interfaces, loader, methodsArray, exceptionsArray); } }// 动态生成代理类class private static native Class<?> generateProxy(String name, Class<?>[] interfaces, ClassLoader loader, Method[] methods, Class<?>[][] exceptions); }

3.2 Retrofit动态代理

Retrofit是一个开源网络库,其源码中也使用到了动态代理模式。简单介绍如下:

3.2.1 基础用法

首先,新建网络请求对应的接口:

public interface SampleRequestInterface { @HTTP(method = “GET”, path = “/api”, hasBody = true) Call getCall(); }

然后,使用Retrofit动态代理生成请求:

public class MainActivity { private void sendRequest() { try { Retrofit retrofit = new Retrofit.Builder() .baseUrl(“http://graph.baidu.com”) .addConverterFactory(GsonConverterFactory.create()) .build();// 返回请求接口的代理类实例,内部实现是用动态代理实现 SampleRequestInterface sampleRequest = retrofit.create(SampleRequestInterface.class); Call call = sampleRequest.getCall(); // 异步发送请求 call.enqueue(new Callback() { @Override public void onResponse(Call call, Response response) { response.body(); }@Override public void onFailure(Call call, Throwable t) {} }); // 同步发送请求 Response response = call.execute(); response.body(); } catch (Exception exception) { exception.printStackTrace(); } } }

    你可能想看:

    扫描二维码推送至手机访问。

    版权声明:本文由皇冠云发布,如需转载请注明出处。

    本文链接:https://www.idchg.com/info/24182.html

    分享给朋友:

    “AndroidStudio已经关了代理还走代理” 的相关文章

    探索中国电信CN2网络:高速互联的未来新篇章

    中国电信CN2网络作为新一代通信网络的代表,以其卓越的性能和创新的技术,正在重新定义数字时代的互联体验。本文将深入探讨CN2网络的核心优势、应用场景以及它对未来的深远影响,带您了解高速互联的无限可能。中国电信CN2网络:重新定义网络连接在数字化转型的浪潮中,网络性能已成为企业竞争力的关键因素之一。中...

    甲骨文注册流程详解:成功申请的关键步骤与技巧

    甲骨文(Oracle Cloud)的注册流程看似复杂,但只要事先做好准备,整个过程其实非常顺利。我自己在注册时感受到了这一点,以下就是我想和大家分享的步骤和经验。 申请前的准备工作 在我们开始注册之前,有几个准备工作是必须要做的。首先,创建一个国际邮箱是至关重要的。虽然国内的邮箱也可以使用,但我推荐...

    搬瓦工VPS服务使用指南与优惠码获取技巧

    搬瓦工(BandwagonHost)是一家成立于2004年的网络服务公司,隶属于加拿大IT7。这家公司的崛起与它提供的超低价格VPS服务密不可分,尤其是在中国市场,搬瓦工已经积累了大量的用户和知名度。随着时间的推移,搬瓦工不仅没有止步于低价策略,而是逐渐向中高端VPS市场发展,推出了诸如CN2 GI...

    高性能HKT VPS服务评测与应用指南

    HKT VPS概述 什么是HKT VPS HKT VPS其实就是基于香港HKT网络架构的虚拟专用服务器,提供了强大的性能和灵活的可配置性。我从多个服务商的不同产品中了解到,HKT VPS非常适合对网络速度和稳定性要求较高的用户。无论是游戏玩家还是企业用户,都能通过它享受到快速的上传和下载速度。 HK...

    Rocky Linux 更新源配置及优化方法

    我最近对Rocky Linux这款操作系统有了更深入的了解。Rocky Linux是一个以开源为基础的企业级操作系统,跟Red Hat Enterprise Linux(RHEL)兼容。它的设计宗旨在于为用户提供一个稳定和可靠的平台。因此,更新源就显得非常重要,影响着系统的升级和软件的安装。 选择合...

    黑五狂欢购物攻略:如何高效享受黑色星期五折扣

    黑五,全称“黑色星期五”(Black Friday),是每年感恩节后的第一天。随着这个节日的到来,许多商店和电商都会推出琳琅满目的促销活动,标志着圣诞购物季的开端。我第一次听到黑五,是在朋友们热火朝天地讨论即将到来的折扣和特卖,这种热情真是难以抗拒。 黑五起源于美国,为什么叫“黑色”呢?这个名字其实...