2024年Android最新Android代理模式基础(1),银行软件开发面试题目

最后

Android学习是一条漫长的道路,我们要学习的东西不仅仅只有表面的 技术,还要深入底层,弄明白下面的 原理,只有这样,我们才能够提高自己的竞争力,在当今这个竞争激烈的世界里立足。

人生不可能一帆风顺,有高峰自然有低谷,要相信,那些打不倒我们的,终将使我们更强大,要做自己的摆渡人。

资源持续更新中,欢迎大家一起学习和探讨。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

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();

最后

对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!

最后,我再重复一次,如果你想成为一个优秀的 Android 开发人员,请集中精力,对基础和重要的事情做深度研究

对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。

以下是今天给大家分享的一些独家干货:

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

独家干货:

[外链图片转存中…(img-l83vG4JN-1715710264718)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 7
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值