Android Retrofit 框架适配器模块深入源码分析(五)
Android Retrofit 框架适配器模块深入源码分析
一、引言
在 Android 开发中,网络请求是一个常见且重要的功能。Retrofit 作为一个强大的网络请求框架,以其简洁的 API 和高度的可定制性受到了广泛的欢迎。适配器模块(CallAdapter)是 Retrofit 框架中非常重要的一部分,它负责将 Call 对象转换为其他类型,如 Observable、Completable、Single 等,从而实现不同的异步编程模式。通过对 Retrofit 适配器模块的源码分析,我们可以深入了解其工作原理,从而更好地使用和扩展这个框架。
二、适配器模块的核心概念
2.1 CallAdapter 接口
CallAdapter 接口是适配器模块的核心接口,它定义了将 Call 对象转换为其他类型的方法。以下是 CallAdapter 接口的源码:
java
// CallAdapter 接口定义了将 Call 对象转换为其他类型的方法
public interface CallAdapter<R, T> {// 获取响应类型Type responseType();// 将 Call 对象转换为其他类型T adapt(Call<R> call);// 工厂类,用于创建 CallAdapter 对象abstract class Factory {// 创建 CallAdapter 对象public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,Retrofit retrofit);// 辅助方法,用于获取泛型类型参数protected static Type getParameterUpperBound(int index, ParameterizedType type) {return Utils.getParameterUpperBound(index, type);}// 辅助方法,用于获取原始类型protected static Class<?> getRawType(Type type) {return Utils.getRawType(type);}}
}
这个接口定义了两个方法:responseType 方法用于获取响应类型,adapt 方法用于将 Call 对象转换为其他类型。Factory 抽象类是用于创建 CallAdapter 对象的工厂类,其中 get 方法用于根据返回类型和注解创建 CallAdapter 对象。
2.2 Retrofit 类中的相关方法
Retrofit 类是 Retrofit 框架的核心类,它包含了与适配器模块相关的方法。以下是部分相关源码:
java
public final class Retrofit {// 适配器工厂列表private final List<CallAdapter.Factory> callAdapterFactories;Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,List<Converter.Factory> converterFactories, List<CallAdapter.Factory> callAdapterFactories,Executor callbackExecutor, boolean validateEagerly) {this.callFactory = callFactory;this.baseUrl = baseUrl;// 保存适配器工厂列表this.callAdapterFactories = unmodifiableList(callAdapterFactories);this.converterFactories = unmodifiableList(converterFactories);this.callbackExecutor = callbackExecutor;this.validateEagerly = validateEagerly;}// 创建 CallAdapter 对象private CallAdapter<Object, Object> createCallAdapter(Method method) {Type returnType = method.getGenericReturnType();Annotation[] annotations = method.getAnnotations();try {// 遍历适配器工厂列表,查找合适的适配器工厂for (CallAdapter.Factory factory : callAdapterFactories) {// 调用工厂的 get 方法创建 CallAdapter 对象CallAdapter<?, ?> adapter = factory.get(returnType, annotations, this);if (adapter != null) {// 找到合适的适配器,返回return (CallAdapter<Object, Object>) adapter;}}} catch (RuntimeException e) {throw methodError(method, e, "Unable to create call adapter for %s", returnType);}throw methodError(method, "Could not locate call adapter for %s.", returnType);}
}
Retrofit 类中保存了一个 callAdapterFactories 列表,用于存储所有的适配器工厂。createCallAdapter 方法用于创建 CallAdapter 对象,它会遍历 callAdapterFactories 列表,调用每个工厂的 get 方法,直到找到合适的适配器为止。
三、常见的适配器工厂实现
3.1 DefaultCallAdapterFactory
DefaultCallAdapterFactory 是 Retrofit 提供的默认适配器工厂,它处理 Call 类型的返回值。以下是其源码分析:
java
// 默认的 CallAdapter 工厂类
final class DefaultCallAdapterFactory extends CallAdapter.Factory {private final @Nullable Executor callbackExecutor;DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {this.callbackExecutor = callbackExecutor;}// 创建 CallAdapter 对象@Overridepublic @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,Retrofit retrofit) {// 检查返回类型是否为 Call 类型if (getRawType(returnType) != Call.class) {return null;}// 检查返回类型是否为参数化类型if (!(returnType instanceof ParameterizedType)) {throw new IllegalStateException("Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");}// 获取泛型类型参数final Type responseType = getParameterUpperBound(0, (ParameterizedType) returnType);final Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)? null: callbackExecutor;// 返回 CallAdapter 对象return new CallAdapter<Object, Call<?>>() {@Overridepublic Type responseType() {return responseType;}@Overridepublic Call<Object> adapt(Call<Object> call) {return executor == null? call: new ExecutorCallbackCall<>(executor, call);}};}// 带有回调执行器的 Call 包装类static final class ExecutorCallbackCall<T> implements Call<T> {final Executor callbackExecutor;final Call<T> delegate;ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {this.callbackExecutor = callbackExecutor;this.delegate = delegate;}@Overridepublic void enqueue(final Callback<T> callback) {// 检查回调是否为空checkNotNull(callback, "callback == null");delegate.enqueue(new Callback<T>() {@Overridepublic void onResponse(Call<T> call, final Response<T> response) {// 在回调执行器中执行回调callbackExecutor.execute(new Runnable() {@Overridepublic void run() {if (delegate.isCanceled()) {// 如果请求已取消,调用回调的 onFailure 方法callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));} else {// 调用回调的 onResponse 方法callback.onResponse(ExecutorCallbackCall.this, response);}}});}@Overridepublic void onFailure(Call<T> call, final Throwable t) {// 在回调执行器中执行回调callbackExecutor.execute(new Runnable() {@Overridepublic void run() {// 调用回调的 onFailure 方法callback.onFailure(ExecutorCallbackCall.this, t);}});}});}@Overridepublic boolean isExecuted() {return delegate.isExecuted();}@Overridepublic Response<T> execute() throws IOException {return delegate.execute();}@Overridepublic void cancel() {delegate.cancel();}@Overridepublic boolean isCanceled() {return delegate.isCanceled();}@SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.@Overridepublic Call<T> clone() {return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());}@Overridepublic Request request() {return delegate.request();}}
}
3.1.1 DefaultCallAdapterFactory 类
DefaultCallAdapterFactory 类实现了 CallAdapter.Factory 抽象类,其 get 方法首先检查返回类型是否为 Call 类型,然后获取泛型类型参数。如果需要回调执行器,则返回一个 ExecutorCallbackCall 对象,否则返回原始的 Call 对象。
3.1.2 ExecutorCallbackCall 类
ExecutorCallbackCall 类是一个 Call 的包装类,它在 enqueue 方法中,将回调的 onResponse 和 onFailure 方法放在回调执行器中执行,以确保回调在指定的线程中执行。
3.2 RxJava2CallAdapterFactory
RxJava2CallAdapterFactory 是 Retrofit 与 RxJava 2 集成的适配器工厂,它可以将 Call 对象转换为 Observable、Single、Completable 等 RxJava 类型。以下是其源码分析:
java
// RxJava2 的 CallAdapter 工厂类
public final class RxJava2CallAdapterFactory extends CallAdapter.Factory {private final @Nullable Scheduler scheduler;private final boolean isAsync;// 创建 RxJava2CallAdapterFactory 实例public static RxJava2CallAdapterFactory create() {return new RxJava2CallAdapterFactory(null, false);}// 创建 RxJava2CallAdapterFactory 实例,指定调度器public static RxJava2CallAdapterFactory createWithScheduler(Scheduler scheduler) {checkNotNull(scheduler, "scheduler == null");return new RxJava2CallAdapterFactory(scheduler, false);}RxJava2CallAdapterFactory(@Nullable Scheduler scheduler, boolean isAsync) {this.scheduler = scheduler;this.isAsync = isAsync;}// 创建 CallAdapter 对象@Overridepublic @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,Retrofit retrofit) {// 获取原始类型Class<?> rawType = getRawType(returnType);boolean isFlowable = rawType == Flowable.class;boolean isSingle = rawType == Single.class;boolean isMaybe = rawType == Maybe.class;boolean isCompletable = rawType == Completable.class;if (rawType != Observable.class && !isFlowable && !isSingle && !isMaybe && !isCompletable) {return null;}// 检查返回类型是否为参数化类型if (!(returnType instanceof ParameterizedType)) {String name = isFlowable ? "Flowable" : isSingle ? "Single" : isMaybe ? "Maybe": isCompletable ? "Completable" : "Observable";throw new IllegalStateException(name + " return type must be parameterized"+ " as " + name + "<Foo> or " + name + "<? extends Foo>");}// 获取泛型类型参数Type responseType = getParameterUpperBound(0, (ParameterizedType) returnType);boolean isResult = false;boolean isBody = false;Class<?> rawWrapperType = getRawType(responseType);if (rawWrapperType == Response.class) {if (!(responseType instanceof ParameterizedType)) {throw new IllegalStateException("Response must be parameterized"+ " as Response<Foo> or Response<? extends Foo>");}responseType = getParameterUpperBound(0, (ParameterizedType) responseType);} else if (rawWrapperType == Result.class) {if (!(responseType instanceof ParameterizedType)) {throw new IllegalStateException("Result must be parameterized"+ " as Result<Foo> or Result<? extends Foo>");}responseType = getParameterUpperBound(0, (ParameterizedType) responseType);isResult = true;} else {isBody = true;}Scheduler scheduler = this.scheduler;if (scheduler == null) {boolean isAsync = Utils.isAnnotationPresent(annotations, Async.class);scheduler = isAsync ? Schedulers.io() : null;}// 返回 CallAdapter 对象if (isCompletable) {return new RxJava2CallAdapter(Void.class, scheduler, isAsync, isResult, isBody, false);} else if (isFlowable) {return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, true);} else if (isSingle) {return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, false);} else if (isMaybe) {return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, false);} else {return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, false);}}
}// RxJava2 的 CallAdapter 实现类
final class RxJava2CallAdapter<R> implements CallAdapter<R, Object> {private final Type responseType;private final @Nullable Scheduler scheduler;private final boolean isAsync;private final boolean isResult;private final boolean isBody;private final boolean isFlowable;RxJava2CallAdapter(Type responseType, @Nullable Scheduler scheduler, boolean isAsync,boolean isResult, boolean isBody, boolean isFlowable) {this.responseType = responseType;this.scheduler = scheduler;this.isAsync = isAsync;this.isResult = isResult;this.isBody = isBody;this.isFlowable = isFlowable;}@Overridepublic Type responseType() {return responseType;}@Overridepublic Object adapt(Call<R> call) {Observable<Response<R>> responseObservable = isAsync? new CallEnqueueObservable<>(call): new CallExecuteObservable<>(call);Observable<?> observable;if (isResult) {observable = new ResultObservable<>(responseObservable);} else if (isBody) {observable = new BodyObservable<>(responseObservable);} else {observable = responseObservable;}if (scheduler != null) {observable = observable.subscribeOn(scheduler);}if (isFlowable) {return observable.toFlowable(BackpressureStrategy.LATEST);} else if (isSingle) {return observable.singleOrError();} else if (isMaybe) {return observable.singleElement();} else if (isCompletable) {return observable.ignoreElements();} else {return observable;}}
}// 异步调用的 Observable 实现类
final class CallEnqueueObservable<T> extends Observable<Response<T>> {private final Call<T> originalCall;CallEnqueueObservable(Call<T> originalCall) {this.originalCall = originalCall;}@Overrideprotected void subscribeActual(Observer<? super Response<T>> observer) {// 克隆原始的 Call 对象Call<T> call = originalCall.clone();observer.onSubscribe(new CallDisposable(call));call.enqueue(new Callback<T>() {@Overridepublic void onResponse(Call<T> call, Response<T> response) {if (call.isCanceled()) return;observer.onNext(response);observer.onComplete();}@Overridepublic void onFailure(Call<T> call, Throwable t) {if (call.isCanceled()) return;observer.onError(t);}});}private static final class CallDisposable implements Disposable {private final Call<?> call;CallDisposable(Call<?> call) {this.call = call;}@Overridepublic void dispose() {call.cancel();}@Overridepublic boolean isDisposed() {return call.isCanceled();}}
}// 同步调用的 Observable 实现类
final class CallExecuteObservable<T> extends Observable<Response<T>> {private final Call<T> originalCall;CallExecuteObservable(Call<T> originalCall) {this.originalCall = originalCall;}@Overrideprotected void subscribeActual(Observer<? super Response<T>> observer) {// 克隆原始的 Call 对象Call<T> call = originalCall.clone();observer.onSubscribe(new CallDisposable(call));boolean terminated = false;try {// 执行同步调用Response<T> response = call.execute();if (!call.isCanceled()) {observer.onNext(response);}if (!call.isCanceled()) {terminated = true;observer.onComplete();}} catch (Throwable t) {Exceptions.throwIfFatal(t);if (terminated) {RxJavaPlugins.onError(t);} else if (!call.isCanceled()) {try {observer.onError(t);} catch (Throwable inner) {Exceptions.throwIfFatal(inner);RxJavaPlugins.onError(new CompositeException(t, inner));}}}}private static final class CallDisposable implements Disposable {private final Call<?> call;CallDisposable(Call<?> call) {this.call = call;}@Overridepublic void dispose() {call.cancel();}@Overridepublic boolean isDisposed() {return call.isCanceled();}}
}// 处理结果的 Observable 实现类
final class ResultObservable<T> extends Observable<Result<T>> {private final Observable<Response<T>> upstream;ResultObservable(Observable<Response<T>> upstream) {this.upstream = upstream;}@Overrideprotected void subscribeActual(Observer<? super Result<T>> observer) {upstream.subscribe(new ResultObserver<>(observer));}private static final class ResultObserver<R> implements Observer<Response<R>> {private final Observer<? super Result<R>> observer;ResultObserver(Observer<? super Result<R>> observer) {this.observer = observer;}@Overridepublic void onSubscribe(Disposable d) {observer.onSubscribe(d);}@Overridepublic void onNext(Response<R> response) {observer.onNext(Result.response(response));}@Overridepublic void onError(Throwable t) {try {observer.onNext(Result.error(t));} catch (Throwable inner) {Exceptions.throwIfFatal(inner);RxJavaPlugins.onError(new CompositeException(t, inner));}observer.onComplete();}@Overridepublic void onComplete() {observer.onComplete();}}
}// 处理响应体的 Observable 实现类
final class BodyObservable<T> extends Observable<T> {private final Observable<Response<T>> upstream;BodyObservable(Observable<Response<T>> upstream) {this.upstream = upstream;}@Overrideprotected void subscribeActual(Observer<? super T> observer) {upstream.subscribe(new BodyObserver<>(observer));}private static final class BodyObserver<R> implements Observer<Response<R>> {private final Observer<? super R> observer;private boolean terminated;BodyObserver(Observer<? super R> observer) {this.observer = observer;}@Overridepublic void onSubscribe(Disposable d) {observer.onSubscribe(d);}@Overridepublic void onNext(Response<R> response) {if (response.isSuccessful()) {observer.onNext(response.body());} else {terminated = true;Throwable t = new HttpException(response);try {observer.onError(t);} catch (Throwable inner) {Exceptions.throwIfFatal(inner);RxJavaPlugins.onError(new CompositeException(t, inner));}}}@Overridepublic void onError(Throwable t) {if (!terminated) {observer.onError(t);} else {// This should never happen! onNext handles and forwards errors automatically.Throwable broken = new AssertionError("This should never happen! Report as a bug with the full stacktrace.");//noinspection UnnecessaryInitCause Two-arg AssertionError constructor is 1.7+ only.broken.initCause(t);RxJavaPlugins.onError(broken);}}@Overridepublic void onComplete() {if (!terminated) {observer.onComplete();}}}
}
3.2.1 RxJava2CallAdapterFactory 类
RxJava2CallAdapterFactory 类实现了 CallAdapter.Factory 抽象类,其 get 方法首先检查返回类型是否为 RxJava 类型(如 Observable、Flowable、Single、Maybe、Completable),然后获取泛型类型参数。根据不同的情况,返回不同的 RxJava2CallAdapter 对象。
3.2.2 RxJava2CallAdapter 类
RxJava2CallAdapter 类实现了 CallAdapter 接口,其 adapt 方法根据不同的配置,将 Call 对象转换为不同的 RxJava 类型。例如,如果是异步调用,使用 CallEnqueueObservable;如果是同步调用,使用 CallExecuteObservable。
3.2.3 CallEnqueueObservable 类
CallEnqueueObservable 类是一个 Observable 的实现类,它在 subscribeActual 方法中,使用 Call 的 enqueue 方法进行异步调用,并将结果传递给观察者。
3.2.4 CallExecuteObservable 类
CallExecuteObservable 类是一个 Observable 的实现类,它在 subscribeActual 方法中,使用 Call 的 execute 方法进行同步调用,并将结果传递给观察者。
3.2.5 ResultObservable 类
ResultObservable 类是一个 Observable 的实现类,它将 Response 对象包装成 Result 对象,并传递给观察者。
3.2.6 BodyObservable 类
BodyObservable 类是一个 Observable 的实现类,它将 Response 对象的响应体传递给观察者,如果响应不成功,则抛出 HttpException 异常。
四、适配器模块的工作流程
4.1 创建 Retrofit 实例时添加适配器工厂
java
// 创建 Retrofit 实例时添加 RxJava2CallAdapterFactory
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.example.com/").addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build();
在创建 Retrofit 实例时,通过 addCallAdapterFactory 方法添加适配器工厂,这些工厂会被添加到 Retrofit 类的 callAdapterFactories 列表中。
4.2 接口方法调用时创建适配器
java
// 定义 API 接口
public interface ApiService {@GET("users/{id}")Observable<User> getUser(@Path("id") int id);
}// 创建 API 服务实例
ApiService apiService = retrofit.create(ApiService.class);
Observable<User> observable = apiService.getUser(1);
当调用 API 接口方法时,Retrofit 会根据方法的返回类型,调用 createCallAdapter 方法,遍历 callAdapterFactories 列表,查找合适的适配器工厂并创建适配器。
4.3 适配器将 Call 对象转换为其他类型
java
// 在 RxJava2CallAdapter 类中进行转换
final class RxJava2CallAdapter<R> implements CallAdapter<R, Object> {@Overridepublic Object adapt(Call<R> call) {Observable<Response<R>> responseObservable = isAsync? new CallEnqueueObservable<>(call): new CallExecuteObservable<>(call);Observable<?> observable;if (isResult) {observable = new ResultObservable<>(responseObservable);} else if (isBody) {observable = new BodyObservable<>(responseObservable);} else {observable = responseObservable;}if (scheduler != null) {observable = observable.subscribeOn(scheduler);}if (isFlowable) {return observable.toFlowable(BackpressureStrategy.LATEST);} else if (isSingle) {return observable.singleOrError();} else if (isMaybe) {return observable.singleElement();} else if (isCompletable) {return observable.ignoreElements();} else {return observable;}}
}
在 adapt 方法中,根据不同的配置,将 Call 对象转换为不同的 RxJava 类型,如 Observable、Flowable、Single、Maybe、Completable 等。
五、自定义适配器工厂
5.1 自定义适配器接口
java
// 自定义 CallAdapter 接口
public interface CustomCallAdapter<R, T> {// 获取响应类型Type responseType();// 将 Call 对象转换为其他类型T adapt(Call<R> call);
}// 自定义 CallAdapter 工厂接口
public abstract class CustomCallAdapterFactory extends CallAdapter.Factory {public abstract @Nullable CustomCallAdapter<?, ?> get(Type returnType, Annotation[] annotations,Retrofit retrofit);
}
首先定义自定义的适配器接口 CustomCallAdapter 和适配器工厂接口 CustomCallAdapterFactory。
5. 自定义适配器工厂
5.2 实现自定义适配器工厂
以下是一个简单的自定义适配器工厂示例,该适配器工厂将 Call 对象转换为自定义的 CustomWrapper 类型。
java
import java.lang.reflect.Type;
import java.util.concurrent.Executor;import retrofit2.Call;
import retrofit2.CallAdapter;
import retrofit2.Retrofit;// 自定义包装类
class CustomWrapper<T> {private final Call<T> call;CustomWrapper(Call<T> call) {this.call = call;}public Call<T> getCall() {return call;}
}// 自定义 CallAdapter 实现
class CustomCallAdapter<R> implements CallAdapter<R, CustomWrapper<R>> {private final Type responseType;private final Executor callbackExecutor;CustomCallAdapter(Type responseType, Executor callbackExecutor) {this.responseType = responseType;this.callbackExecutor = callbackExecutor;}@Overridepublic Type responseType() {return responseType;}@Overridepublic CustomWrapper<R> adapt(Call<R> call) {// 这里可以添加一些自定义逻辑,比如线程调度等return new CustomWrapper<>(call);}
}// 自定义 CallAdapter 工厂实现
class CustomCallAdapterFactory extends CallAdapter.Factory {private final Executor callbackExecutor;CustomCallAdapterFactory(Executor callbackExecutor) {this.callbackExecutor = callbackExecutor;}@Overridepublic CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {// 检查返回类型是否为自定义的 CustomWrapper 类型if (getRawType(returnType) != CustomWrapper.class) {return null;}// 检查返回类型是否为参数化类型if (!(returnType instanceof ParameterizedType)) {throw new IllegalStateException("CustomWrapper return type must be parameterized as CustomWrapper<Foo>");}// 获取泛型类型参数Type responseType = getParameterUpperBound(0, (ParameterizedType) returnType);return new CustomCallAdapter<>(responseType, callbackExecutor);}
}
代码解释:
- CustomWrapper 类:这是一个简单的包装类,用于包装
Call对象。 - CustomCallAdapter 类:实现了
CallAdapter接口,负责将Call对象转换为CustomWrapper对象。adapt方法中可以添加一些自定义的逻辑,例如线程调度等。 - CustomCallAdapterFactory 类:实现了
CallAdapter.Factory抽象类,get方法用于检查返回类型是否为CustomWrapper类型,如果是,则创建并返回CustomCallAdapter实例。
5.3 使用自定义适配器工厂
java
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;import retrofit2.Retrofit;
import retrofit2.Call;
import retrofit2.http.GET;// 定义 API 接口
interface CustomApiService {@GET("data")CustomWrapper<String> getData();
}public class Main {public static void main(String[] args) {// 创建回调执行器Executor callbackExecutor = Executors.newSingleThreadExecutor();// 创建 Retrofit 实例并添加自定义适配器工厂Retrofit retrofit = new Retrofit.Builder().baseUrl("https://example.com/").addCallAdapterFactory(new CustomCallAdapterFactory(callbackExecutor)).build();// 创建 API 服务实例CustomApiService apiService = retrofit.create(CustomApiService.class);// 调用接口方法CustomWrapper<String> wrapper = apiService.getData();Call<String> call = wrapper.getCall();// 执行请求call.enqueue(new retrofit2.Callback<String>() {@Overridepublic void onResponse(Call<String> call, retrofit2.Response<String> response) {if (response.isSuccessful()) {System.out.println("Response: " + response.body());} else {System.out.println("Error: " + response.code());}}@Overridepublic void onFailure(Call<String> call, Throwable t) {System.out.println("Failure: " + t.getMessage());}});}
}
代码解释:
- CustomApiService 接口:定义了一个返回
CustomWrapper<String>类型的接口方法。 - Main 类:创建了一个
Retrofit实例,并添加了自定义的适配器工厂。然后创建了 API 服务实例,调用接口方法,最后执行请求并处理响应。
六、适配器模块的异常处理
6.1 创建适配器时的异常处理
在 Retrofit 类的 createCallAdapter 方法中,会遍历适配器工厂列表来创建适配器。如果在创建过程中出现异常,会捕获并抛出相应的错误信息。
java
public final class Retrofit {// ... 其他代码 ...private CallAdapter<Object, Object> createCallAdapter(Method method) {Type returnType = method.getGenericReturnType();Annotation[] annotations = method.getAnnotations();try {// 遍历适配器工厂列表,查找合适的适配器工厂for (CallAdapter.Factory factory : callAdapterFactories) {// 调用工厂的 get 方法创建 CallAdapter 对象CallAdapter<?, ?> adapter = factory.get(returnType, annotations, this);if (adapter != null) {// 找到合适的适配器,返回return (CallAdapter<Object, Object>) adapter;}}} catch (RuntimeException e) {// 捕获创建适配器过程中可能出现的运行时异常throw methodError(method, e, "Unable to create call adapter for %s", returnType);}throw methodError(method, "Could not locate call adapter for %s.", returnType);}// ... 其他代码 ...
}
代码解释:
- 如果在调用
factory.get方法时抛出RuntimeException,会将其封装成methodError异常抛出,提示无法为指定的返回类型创建适配器。 - 如果遍历完所有适配器工厂都没有找到合适的适配器,也会抛出
methodError异常。
6.2 适配器转换过程中的异常处理
在适配器的 adapt 方法中,也可能会出现异常。例如,在 RxJava2CallAdapter 中,如果在创建 Observable 或进行类型转换时出现异常,会通过 RxJava 的错误处理机制进行处理。
java
final class RxJava2CallAdapter<R> implements CallAdapter<R, Object> {// ... 其他代码 ...@Overridepublic Object adapt(Call<R> call) {try {Observable<Response<R>> responseObservable = isAsync? new CallEnqueueObservable<>(call): new CallExecuteObservable<>(call);Observable<?> observable;if (isResult) {observable = new ResultObservable<>(responseObservable);} else if (isBody) {observable = new BodyObservable<>(responseObservable);} else {observable = responseObservable;}if (scheduler != null) {observable = observable.subscribeOn(scheduler);}if (isFlowable) {return observable.toFlowable(BackpressureStrategy.LATEST);} else if (isSingle) {return observable.singleOrError();} else if (isMaybe) {return observable.singleElement();} else if (isCompletable) {return observable.ignoreElements();} else {return observable;}} catch (Exception e) {// 处理异常,这里可以根据具体需求进行日志记录或其他操作throw new RuntimeException("Error adapting Call to RxJava type", e);}}
}
代码解释:
- 在
adapt方法中,使用try-catch块捕获可能出现的异常。如果出现异常,会抛出一个新的RuntimeException,并将原始异常作为 cause 传递。
6.3 异步调用中的异常处理
在异步调用中,如 CallEnqueueObservable 中,会在 onFailure 方法中处理请求失败的异常,并将其传递给观察者。
java
final class CallEnqueueObservable<T> extends Observable<Response<T>> {// ... 其他代码 ...@Overrideprotected void subscribeActual(Observer<? super Response<T>> observer) {// 克隆原始的 Call 对象Call<T> call = originalCall.clone();observer.onSubscribe(new CallDisposable(call));call.enqueue(new Callback<T>() {@Overridepublic void onResponse(Call<T> call, Response<T> response) {if (call.isCanceled()) return;observer.onNext(response);observer.onComplete();}@Overridepublic void onFailure(Call<T> call, Throwable t) {if (call.isCanceled()) return;observer.onError(t);}});}// ... 其他代码 ...
}
代码解释:
- 当
Call的enqueue方法调用失败时,会调用onFailure方法,将异常t传递给观察者的onError方法。
七、适配器模块的性能优化
7.1 缓存适配器
为了避免每次调用接口方法时都创建新的适配器,可以使用缓存机制。以下是一个简单的缓存实现示例:
java
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;class CallAdapterCache {private static final Map<Type, CallAdapter<?, ?>> cache = new HashMap<>();public static <R, T> CallAdapter<R, T> getAdapter(Type returnType, CallAdapter.Factory factory, Retrofit retrofit) {@SuppressWarnings("unchecked")CallAdapter<R, T> adapter = (CallAdapter<R, T>) cache.get(returnType);if (adapter == null) {adapter = (CallAdapter<R, T>) factory.get(returnType, new Annotation[0], retrofit);if (adapter != null) {cache.put(returnType, adapter);}}return adapter;}
}// 修改 Retrofit 类的 createCallAdapter 方法
public final class Retrofit {// ... 其他代码 ...private CallAdapter<Object, Object> createCallAdapter(Method method) {Type returnType = method.getGenericReturnType();Annotation[] annotations = method.getAnnotations();try {for (CallAdapter.Factory factory : callAdapterFactories) {CallAdapter<Object, Object> adapter = CallAdapterCache.getAdapter(returnType, factory, this);if (adapter != null) {return adapter;}}} catch (RuntimeException e) {throw methodError(method, e, "Unable to create call adapter for %s", returnType);}throw methodError(method, "Could not locate call adapter for %s.", returnType);}// ... 其他代码 ...
}
代码解释:
CallAdapterCache类使用一个HashMap来缓存适配器。getAdapter方法首先检查缓存中是否存在对应的适配器,如果存在则直接返回,否则调用工厂的get方法创建适配器并缓存起来。- 修改
Retrofit类的createCallAdapter方法,使用缓存来获取适配器。
7.2 减少不必要的类型转换
在适配器的 adapt 方法中,尽量减少不必要的类型转换和中间对象的创建。例如,在 RxJava2CallAdapter 中,避免在不必要的情况下进行 Observable 的多次转换。
java
final class RxJava2CallAdapter<R> implements CallAdapter<R, Object> {// ... 其他代码 ...@Overridepublic Object adapt(Call<R> call) {Observable<Response<R>> responseObservable = isAsync? new CallEnqueueObservable<>(call): new CallExecuteObservable<>(call);Observable<?> observable;if (isResult) {observable = new ResultObservable<>(responseObservable);} else if (isBody) {observable = new BodyObservable<>(responseObservable);} else {observable = responseObservable;}if (scheduler != null) {observable = observable.subscribeOn(scheduler);}// 避免不必要的转换if (isFlowable) {return observable.toFlowable(BackpressureStrategy.LATEST);} else if (isSingle) {return observable.singleOrError();} else if (isMaybe) {return observable.singleElement();} else if (isCompletable) {return observable.ignoreElements();}return observable;}
}
代码解释:
- 在
adapt方法中,根据不同的配置直接返回相应的 RxJava 类型,避免不必要的中间转换。
7.3 合理选择调度器
在使用 RxJava 适配器时,合理选择调度器可以提高性能。例如,如果是网络请求,通常使用 Schedulers.io() 来进行异步操作,避免阻塞主线程。
java
// 在 RxJava2CallAdapterFactory 中设置调度器
public final class RxJava2CallAdapterFactory extends CallAdapter.Factory {private final @Nullable Scheduler scheduler;private final boolean isAsync;// ... 其他代码 ...RxJava2CallAdapterFactory(@Nullable Scheduler scheduler, boolean isAsync) {this.scheduler = scheduler;this.isAsync = isAsync;}@Overridepublic @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,Retrofit retrofit) {// ... 其他代码 ...Scheduler scheduler = this.scheduler;if (scheduler == null) {boolean isAsync = Utils.isAnnotationPresent(annotations, Async.class);scheduler = isAsync ? Schedulers.io() : null;}// ... 其他代码 ...}
}
代码解释:
- 在
RxJava2CallAdapterFactory中,如果没有指定调度器,且是异步调用,则使用Schedulers.io()作为调度器。
八、适配器模块与其他模块的交互
8.1 与数据转换模块的交互
适配器模块和数据转换模块在请求和响应处理过程中相互协作。数据转换模块负责将请求参数序列化为 HTTP 请求体,以及将 HTTP 响应体反序列化为 Java 对象;适配器模块负责将 Call 对象转换为其他类型。
java
// 定义 API 接口
public interface ApiService {@GET("users/{id}")Observable<User> getUser(@Path("id") int id);
}Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.example.com/").addConverterFactory(GsonConverterFactory.create()) // 添加数据转换工厂.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 添加适配器工厂.build();ApiService apiService = retrofit.create(ApiService.class);
Observable<User> observable = apiService.getUser(1);
代码解释:
GsonConverterFactory负责将响应体转换为User对象,RxJava2CallAdapterFactory负责将Call对象转换为Observable对象。
8.2 与 OkHttp 模块的交互
Retrofit 底层使用 OkHttp 进行网络请求,适配器模块和 OkHttp 模块在请求和响应处理上进行交互。OkHttp 负责发送请求和接收响应,适配器模块负责将 Call 对象转换为其他类型。
java
final class OkHttpCall<T> implements Call<T> {// ... 其他代码 ...@Overridepublic void enqueue(final Callback<T> callback) {// 检查回调是否为空checkNotNull(callback, "callback == null");delegate.enqueue(new Callback<T>() {@Overridepublic void onResponse(Call<T> call, final Response<T> response) {if (call.isCanceled()) return;// 调用适配器的逻辑,可能会将响应传递给观察者callback.onResponse(OkHttpCall.this, response);}@Overridepublic void onFailure(Call<T> call, final Throwable t) {if (call.isCanceled()) return;// 调用适配器的逻辑,可能会将异常传递给观察者callback.onFailure(OkHttpCall.this, t);}});}// ... 其他代码 ...
}
代码解释:
- 在
OkHttpCall的enqueue方法中,当请求成功或失败时,会调用回调的onResponse或onFailure方法,适配器模块可以在这些回调中进行相应的处理,例如将响应或异常传递给观察者。
九、适配器模块的未来发展趋势
9.1 支持更多的异步编程模型
随着 Android 开发中异步编程模型的不断发展,Retrofit 的适配器模块可能会支持更多的异步编程模型,如 Kotlin 的协程、Java 的 CompletableFuture 等。
9.2 更好的性能优化
未来的适配器模块可能会进行更多的性能优化,例如减少内存开销、提高并发处理能力等。可以通过使用更高效的数据结构和算法来实现这些优化。
9.3 与更多的框架集成
Retrofit 可能会与更多的框架进行集成,如 RxJava 3、Flow 等,以提供更好的开发体验。适配器模块可以提供相应的适配器工厂,方便开发者在不同的框架之间进行切换。
9.4 增强的错误处理和调试功能
适配器模块可能会提供更详细的错误信息和调试工具,帮助开发者更快地定位和解决问题。例如,在异常信息中提供更多的上下文信息,或者提供可视化的调试工具。
十、总结
Retrofit 的适配器模块是一个非常重要的模块,它负责将 Call 对象转换为其他类型,从而实现不同的异步编程模式。通过对适配器模块的源码分析,我们了解了其核心概念、常见的适配器工厂实现、工作流程、异常处理、性能优化、与其他模块的交互以及未来发展趋势。掌握这些知识可以帮助我们更好地使用和扩展 Retrofit 框架,提高开发效率和应用性能。在实际开发中,我们可以根据具体的需求选择合适的适配器工厂,进行自定义适配器的开发,以及对适配器模块进行性能优化,以满足不同的业务需求。同时,我们也需要关注适配器模块的未来发展趋势,以便及时跟上技术的发展步伐。
以上的分析涵盖了 Retrofit 适配器模块的各个方面,从核心概念到源码实现,从异常处理到性能优化,以及与其他模块的交互和未来发展趋势。通过深入理解这些内容,开发者可以更好地利用 Retrofit 的适配器模块来构建高效、灵活的网络请求系统。
请注意,Retrofit 是一个不断发展的框架,以上分析基于其常见的实现和版本,实际情况可能会因版本更新而有所不同。在使用时,建议参考官方文档和最新的源码。
相关文章:
Android Retrofit 框架适配器模块深入源码分析(五)
Android Retrofit 框架适配器模块深入源码分析 一、引言 在 Android 开发中,网络请求是一个常见且重要的功能。Retrofit 作为一个强大的网络请求框架,以其简洁的 API 和高度的可定制性受到了广泛的欢迎。适配器模块(CallAdapter)…...
Node.js模块化与npm
目录 一、模块化简介 二、CommonJS 规范 1. 基本语法 2. 导出模块 3. 导入模块 三、ECMAScript 标准(ESM) 1. 启用 ESM 一、默认导出与导入 1. 基本语法 2. 默认导出(每个模块仅一个) 3. 默认导入 二、命名导出与导入…...
nginx中的代理缓存
1.缓存存放路径 对key取哈希值之后,设置cache内容,然后得到的哈希值的倒数第一位作为第一个子目录,倒数第三位和倒数第二位组成的字符串作为第二个子目录,如图。 proxy_cache_path /xxxx/ levels1:2 2.文件名哈希值...
【前端vue生成二维码和条形码——MQ】
前端vue生成二维码和条形码——MQ 前端vue生成二维码和条形码——MQ一、安装所需要的库1、安装qrcode2、安装jsbarcode 二、使用步骤1、二维码生成2、条形码生成 至此,大功告成! 前端vue生成二维码和条形码——MQ 一、安装所需要的库 1、安装qrcode 1…...
flutter 桌面应用之窗口自定义
在开发桌面软件的时候我们经常需要配置软件的窗口的大小以及位置 我们有两个框架选择:window_manager和bitsdojo_window 对比bitsdojo_window 特性bitsdojo_windowwindow_manager自定义标题栏✅ 支持❌ 不支持控制窗口行为(大小/位置)✅(基本…...
华为OD机试真题——MELON的难题(2025A卷:200分)Java/python/JavaScript/C++/C语言/GO六种最佳实现
2025 A卷 200分 题型 本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析; 并提供Java、python、JavaScript、C、C语言、GO六种语言的最佳实现方式! 2025华为OD真题目录全流程解析/备考攻略/经验分享 华为OD机试真题《MELON的…...
【C++】深入浅出之继承
目录 继承的概念及定义继承的定义继承方式和访问限定符protected与private的区别 默认继承方式继承类模板基类和派生类对象赋值兼容转换继承中的作⽤域(隐藏关系)相关面试题⭐ 派生类的默认成员函数⭐构造函数拷贝构造赋值重载析构函数 继承与友元继承与静态成员继承的方式菱形…...
在 macOS 上切换默认 Java 版本
下载javasdk 打开android studio -> setting -> build.execution,dep -> build tools -> gradle -> Gradle JDK -> download JDK… 点击下载,就下载到了 ~/Library/Java/JavaVirtualMachines/ 安装 jenv brew install jenv将 jenv 集成到 Shell …...
【安卓开发】【Android Studio】Menu(菜单栏)的使用及常见问题
一、菜单栏选项 在项目中添加顶部菜单栏的方法: 在res目录下新建menu文件夹,在该文件夹下新建用于菜单栏的xml文件: 举例说明菜单栏的写法,只添加一个选项元素: <?xml version"1.0" encoding"ut…...
2025.04.17【Stacked area】| 生信数据可视化:堆叠区域图深度解析
文章目录 生信数据可视化:堆叠区域图深度解析堆叠面积图简介为什么使用堆叠面积图如何使用R语言创建堆叠面积图安装和加载ggplot2包创建堆叠面积图的基本步骤示例代码 解读堆叠面积图堆叠面积图的局限性实际应用案例示例:基因表达量随时间变化 结论 生信…...
【NLP】 22. NLP 现代教程:Transformer的训练与应用全景解读
🧠 NLP 现代教程:Transformer的训练与应用全景解读 一、Transformer的使用方式(Training and Use) 如何使用Transformer模型? Transformer 模型最初的使用方式有两种主要方向: 类似 RNN 编码-解码器的架…...
jenkins凭据管理(配置github密钥)
凭据分类 Jenkins可以保存下面几种凭证: Secret text:例如 API Token(例如GitHub的个人access token)。Username with password:指的是登录GitHub的用户名和密码,可以作为单独的组件处理,也可以…...
数据结构|排序算法(三)选择排序 堆排序 归并排序
一、选择排序 1.算法思想 选择排序(Selection Sort)是一种简单直观的排序算法,其基本思想是:每次都从待排序部分中选出最小的一个数据和待排序的第一个数据交换。 将待排序序列分为已排序和未排序两部分,初始时已排…...
MAC Mini M4 上测试Detectron2 图像识别库
断断续续地做图像识别的应用,使用过各种图像识别算法,一开始使用openCV 做教室学生计数的程序。以后又使用YOLO 做医学伤口检测程序。最近,开始使用meta 公司的Detectron2.打算做OCR 文档结构分析 Detectron2 的开发者是 Meta 的 Facebook AI…...
OpenCv高阶(四)——角点检测
一、角点检测 在计算机视觉中,角点检测是识别图像中局部区域(角点)的关键技术,这些区域通常是两条或多条边缘的交点,具有丰富的结构信息,常用于图像匹配、跟踪、三维重建等任务。 Harris角点检测算法是一…...
TOA与AOA联合定位的高精度算法,三维、4个基站的情况,MATLAB例程,附完整代码
本代码实现了三维空间内目标的高精度定位,结合到达角(AOA) 和到达时间(TOA) 两种测量方法,通过4个基站的协同观测,利用最小二乘法解算目标位置。代码支持噪声模拟、误差分析及三维可视化,适用于无人机导航、室内定位等场景。订阅专栏后可获得完整代码 文章目录 运行结果…...
如何在 Ubuntu 22.04 上安装、配置、使用 Nginx
如何在 Ubuntu 22.04 上安装、配置、使用 Nginx?-阿里云开发者社区 更新应用 sudo apt updatesudo apt upgrade检查必要依赖并安装 sudo apt install -y curl gnupg2 ca-certificates lsb-release安装nginx sudo apt install -y nginx# 启动nginx sudo systemct…...
揭秘大数据 | 23、软件定义网络
软件定义网络将网络的边缘从硬件交换机推进到了服务器里面,将服务器和虚拟机的所有部署、管理的职能从原来的系统管理员网络管理员的模式变成了纯系统管理员的模式,让服务器的业务部署变得简单,不再依赖于形态和功能各异的硬件交换机…...
Elastic 9.0/8.18:BBQ、EDOT 和 LLM 可观察性、攻击发现、自动导入以及 ES|QL JOIN
作者:来自 Elastic Brian Bergholm 今天,我们很高兴地宣布 Elastic 9.0 和 8.18 的正式发布! 如果你觉得 8.x 版本系列已经很令人印象深刻,包含了 ANN、TSDB、ELSER、ES|QL、LTR、BBQ、logsdb 索引模式等功能,那你一定…...
当 AI 有了 “万能插头” 和 “通用语言”:MCP 与 A2A 如何重构智能体生态
目录 一、MCP:让 AI 拥有 “万能工具插头” 1.1 从 “手工对接” 到 “即插即用” 1.2 架构解密:AI 如何 “指挥” 工具干活 1.3 安全优势:数据不出门,操作可追溯 二、A2A:让智能体学会 “跨语言协作” 2.1 从 “…...
中间件--ClickHouse-3--列式存储和行式存储理解
在数据库存储中,列式存储(Columnar Storage)与行式存储(Row-based Storage)是两种不同的数据组织方式,它们各自适用于不同类型的应用场景。 1、行式存储(MySQL) 存储方式ÿ…...
【golang/jsonrpc】go-ethereum中json rpc初步使用(websocket版本)
说在前面 操作系统:win11 wsl2go-ethereum版本:1.15.8 关于json-rpc 官网 server 定义方法type CalculatorService struct{}func (s *CalculatorService) Add(a, b int) int {return a b }func (s *CalculatorService) Div(a, b int) (int, error) {…...
逻辑回归 (Logistic Regression)
文章目录 逻辑回归 (Logistic Regression)问题的引出Sigmoid function逻辑回归的解释决策边界 (Decision boundary)逻辑回归的代价函数机器学习中代价函数的设计1. 代价函数的来源(1)从概率模型推导而来(统计学习视角)(…...
燕山大学计算机网络之Java实现TCP数据包结构设计与收发
觉得博主写的好,给博主点点免费的关注吧! 目录 摘要.................................................................................................................... 4 前言.............................................................…...
如何使用SpringApplicationRunListener在Spring Boot 应用的不同生命周期阶段插入自定义逻辑
目录 一、引言二、核心方法概述三、加载机制四、使用场景五、扩展 - 如何在测试的不同阶段插入逻辑5.1 TestExecutionListener & AbstractTestExecutionListener5.1.1 主要功能5.1.2 生命周期方法 5.2 如何集成TestExecutionListener5.3 总结 一、引言 SpringApplicationR…...
P10413 [蓝桥杯 2023 国 A] 圆上的连线
题意: 给定一个圆,圆上有 n2023 个点从 1 到 n 依次编号。 问有多少种不同的连线方式,使得完全没有连线相交。当两个方案连线的数量不同或任何一个点连接的点在另一个方案中编号不同时,两个方案视为不同。 答案可能很大&#x…...
JavaEE——线程安全
目录 前言1.线程安全的定义2.线程安全问题产生的原因2.1 多个线程修改一个变量2.2 修改操作不是原子的2.3 内存可见性引起的线程安全问题 3.解决线程安全问题的方法3.1 通过synchronized关键字加锁3.2 使用volatile关键字 总结 前言 在使用多线程的时候,难免会出现…...
Redis Hash 介绍
Redis Hash 介绍 从基础命令、内部编码和使用场景三个维度分析如下: 一、基础命令 Redis Hash 提供了丰富的操作命令,适用于字段(field)级别的增删改查: 设置与修改 HSET:设置单个字段值(HSET…...
[redis进阶一]redis的持久化(2)AOF篇章
目录 一 为什么有了RDB持久化机制还要有AOF呢 板书介绍具体原因: 编辑二 详细讲解AOF机制 (1)AOF的基本使用 1)板书如下 2)开启AOF机制: 3) AOF工作流程 (2)AOF是否会影响到redis性能 编辑 (3)AOF缓冲区刷新策略 (4)AOF的重写机制 板书如下: 为什么要有这个重写机…...
【Linux我做主】探秘gcc/g++和动静态库
TOC Linux编译器gcc/g的使用 github地址 有梦想的电信狗 前言 在软件开发的世界中,编译器如同匠人的工具,将人类可读的代码转化为机器执行的指令。 对于Linux开发者而言,gcc和g是构建C/C程序的核心工具链,掌握它们的原理和使…...
