其他
都说Retrofit好,好在哪里?只有动态代理么?
https://juejin.cn/post/7329164061391093795
private val baseUrl = "https://www.wanandroid.com/"
private fun fetchLoginByOkHttp(
username: String,
password: String,
) {
val body = FormBody.Builder()
.addEncoded("username", username)
.addEncoded("password", password)
.build()
val request = Request.Builder()
.url("$baseUrl user/login")
.post(body)
.build()
okHttpClient.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
// 失败回调
e.printStackTrace()
}
override fun onResponse(call: Call, response: Response) {
// 成功回调
Log.d(TAG, response.body.toString())
}
})
}
username: String,
password: String,
repeatPassword: String,
) {
val body = FormBody.Builder()
.addEncoded("username", username)
.addEncoded("password", password)
.addEncoded("repassword", repeatPassword)
.build()
val request = Request.Builder()
.url("$baseUrl user/register")
.post(body)
.build()
okHttpClient.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
// 失败回调
e.printStackTrace()
}
override fun onResponse(call: Call, response: Response) {
// 成功回调
Log.d(TAG, response.body.toString())
}
})
}
模版代码出现了
构建请求体的代码写起来好麻烦啊
一个对象应当对其他对象保持尽可能少的了解。 两个对象之间不应发生不必要的直接交互,除非它们是不可分割地绑定的。
interface LoginService {
@POST("user/login")
@FormUrlEncoded
suspend fun login(
@Field("username") username: String,
@Field("password") password: String,
): Result<ApiResponse<LoginResponse>>
@POST("user/register")
suspend fun register(
@Field("username") username: String,
@Field("password") password: String,
@Field("repassword") repeatPassword: String,
): Result<ApiResponse<LoginResponse>>
}
private suspend fun fetchLoginByRetrofit(
username: String,
password: String,
) {
val loginService = retrofit.create(LoginService::class.java)
loginService.login(username, password).onFailure {
// 失败回调
}.onSuccess {
// 成功回调
}
}
消除了模板代码 屏蔽了和调用者无关的处理,完全符合软件设计六大原则中的迪米特法则
Retrofit的构建
.client(okHttpClient)
// 使用Gson进行反序列化
.addConverterFactory(GsonConverterFactory.create())
// 配置Rxjava
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
// 设置baseUrl
.baseUrl(BASE_URL)
.build()
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
List<Converter.Factory> converterFactories =
new ArrayList<>(
1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
converterFactories.addAll(platform.defaultConverterFactories());
return new Retrofit(
callFactory,
baseUrl,
unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories),
callbackExecutor,
validateEagerly);
}
public <T> T create(final Class<T> service) {
validateServiceInterface(service);
return (T)
Proxy.newProxyInstance(
service.getClassLoader(),
new Class<?>[] {service},
new InvocationHandler() {
private final Platform platform = Platform.get();
private final Object[] emptyArgs = new Object[0];
@Override
public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
// If the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
args = args != null ? args : emptyArgs;
return platform.isDefaultMethod(method)
? platform.invokeDefaultMethod(method, service, proxy, args)
: loadServiceMethod(method).invoke(args);
}
});
}
何为动态代理?
JDK 动态代理:使用 Proxy 类和 InvocationHandler 接口来创建代理对象。 CGLIB 代理:使用 CGLIB 库来创建代理对象。
动态代理一秒解决抖动问题
return Proxy.newProxyInstance(this!!::class.java.classLoader, this!!::class.java.interfaces,
object : InvocationHandler {
private var lastInvokeTime = System.currentTimeMillis()
override fun invoke(proxy: Any, method: Method, args: Array<out Any>?): Any? {
val current = System.currentTimeMillis()
return if (current - lastInvokeTime > during) {
lastInvokeTime = current;
method.invoke(this@throttle, *args.orEmpty())
} else {
resolveDefaultReturnValue(method)
}
}
}
) as T
}
private fun resolveDefaultReturnValue(method: Method): Any? {
return when (method.returnType.name.lowercase(Locale.US)) {
Void::class.java.simpleName.lowercase(Locale.US) -> null
else -> throw IllegalArgumentException("throttle只能作用于无返回值函数")
}
}
button.setOnClickListener(View.OnClickListener {
// 此处的代码会被代理,支持防抖
}.throttle())
buttonA.setOnClickListener {
val currentTime = System.System.currentTimeMillis()
if (current - buttonALastClickedTime > 500L) {
lastInvokeTime = current;
// 执行具体的点击业务逻辑
} else {
// 过快点击,进行防抖处理
}
}
buttonB.setOnClickListener {
val currentTime = System.System.currentTimeMillis()
if (current - buttonBLastClickedTime > 500L) {
lastInvokeTime = current;
// 执行具体的点击业务逻辑
} else {
// 过快点击,进行防抖处理
}
}
//省略 buttonC、buttonD...
性能监控 。在Android开发中,动态代理可以用于性能监控,例如测量方法执行的时间。 AOP(面向切面编程)。AOP是一种编程范型,通过预编译方式和运行期动态代理实现程序功能的统一维护,降低业务逻辑各部分之间的耦合度,提高程序的可重用性。 事件处理 。在Android开发中,动态代理可以用于事件处理,例如在方法调用前后执行额外的逻辑。
public <T> T create(final Class<T> service) {
validateServiceInterface(service);
return (T)
Proxy.newProxyInstance(
service.getClassLoader(),
new Class<?>[] {service},
new InvocationHandler() {
private final Platform platform = Platform.get();
private final Object[] emptyArgs = new Object[0];
@Override
public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
// If the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
args = args != null ? args : emptyArgs;
return platform.isDefaultMethod(method)
? platform.invokeDefaultMethod(method, service, proxy, args)
: loadServiceMethod(method).invoke(args);
}
});
}
validateServiceInterface(service)校验service的有效性,与我们的关注点无关,暂且忽略; Proxy.newProxyInstance使用动态代理代理service,重点就在这里。
参数ClassLoader loader:定义代理类接口的类加载器 参数Class<?>[] interfaces:代理类要实现的接口列表 参数InvocationHandler h:将方法调用分派到的调用处理程序 返回值Object:代理实例
ServiceMethod<?> loadServiceMethod(Method method) {
ServiceMethod<?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
// 以上都是缓存相关的逻辑,暂时不必理会,重点是parseAnnotations方法
result = ServiceMethod.parseAnnotations(this, method);
serviceMethodCache.put(method, result);
}
}
return result;
}
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
// 1.解析servie中的注解并保存信息至RequestFactory
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
// 2.获取并校验返回类型
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(
method,
"Method return type must not include a type variable or wildcard: %s",
returnType);
}
if (returnType == void.class) {
throw methodError(method, "Service methods cannot return void.");
}
// 3.调用HttpServiceMethod.parseAnnotations方法创建ServiceMethod
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
.baseUrl("https://api.example.com")
// 添加RxJava适配器
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
.baseUrl("https://api.example.com")
// 添加Gson作为反序列化框架
.addConverterFactory(GsonConverterFactory.create())
.build();
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
boolean continuationWantsResponse = false;
boolean continuationBodyNullable = false;
Annotation[] annotations = method.getAnnotations();
// 1.获取adapterType
Type adapterType;
if (isKotlinSuspendFunction) {
Type[] parameterTypes = method.getGenericParameterTypes();
Type responseType =
Utils.getParameterLowerBound(
0, (ParameterizedType) parameterTypes[parameterTypes.length - 1]);
if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
continuationWantsResponse = true;
} else {
}
adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
} else {
adapterType = method.getGenericReturnType();
}
// 2.根据adapterType创建CallAdapter
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
// 3.校验responseType
Type responseType = callAdapter.responseType();
if (responseType == okhttp3.Response.class) {
throw methodError(
method,
"'"
+ getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
if (responseType == Response.class) {
throw methodError(method, "Response must include generic type (e.g., Response<String>)");
}
if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
throw methodError(method, "HEAD method must use Void as response type.");
}
// 4.创建responseConverter
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory;
// 5.最终创建HttpServiceMethod实例
if (!isKotlinSuspendFunction) {
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
} else if (continuationWantsResponse) {
return (HttpServiceMethod<ResponseT, ReturnT>)
new SuspendForResponse<>(
requestFactory,
callFactory,
responseConverter,
(CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
} else {
return (HttpServiceMethod<ResponseT, ReturnT>)
new SuspendForBody<>(
requestFactory,
callFactory,
responseConverter,
(CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
continuationBodyNullable);
}
}
根据对应的method是否为Kotlin的挂起函数以及responseType的类型获取adapterType,默认为mothod的返回值类型 根据adapterType创建CallAdapter 校验responseType 创建responseConverter 创建HttpServiceMethod实例
创建CallAdapter
private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) {
try {
//noinspection unchecked
return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(method, e, "Unable to create call adapter for %s", returnType);
}
}
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
public CallAdapter<?, ?> nextCallAdapter(
@Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) {
// 省略不相关代码...
int start = callAdapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
// 继续省略...
}
创建HttpServiceMethod实例
CallAdapted,默认类型 SuspendForResponse,兼容Kotlin协程 SuspendForBody,兼容Kotlin协程,与SuspendForResponse不同的是它的返回值是服务器返回的响应体对象 (T),不包含状态码和响应头。
protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
return callAdapter.adapt(call);
}
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
// 省略不相关代码...
return new CallAdapter<Object, Call<?>>() {
public Type responseType() {
return responseType;
}
public Call<Object> adapt(Call<Object> call) {
return (Call)(executor == null ? call : new ExecutorCallbackCall(executor, call));
}
};
}
public void enqueue(final Callback<T> callback) {
Objects.requireNonNull(callback, "callback == null");
this.delegate.enqueue(new Callback<T>() {
public void onResponse(Call<T> call, Response<T> response) {
ExecutorCallbackCall.this.callbackExecutor.execute(() -> {
if (ExecutorCallbackCall.this.delegate.isCanceled()) {
callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
} else {
callback.onResponse(ExecutorCallbackCall.this, response);
}
});
}
public void onFailure(Call<T> call, Throwable t) {
ExecutorCallbackCall.this.callbackExecutor.execute(() -> {
callback.onFailure(ExecutorCallbackCall.this, t);
});
}
});
}