Retrofit

Retrofit guide

Retrofit的核心原理是注解处理器和动态代理。开发人员可以通过在接口上使用注解来定义Web服务的请求。Retrofit的注解处理器会读取这些注解,并根据它们生成HTTP请求的代码。然后,Retrofit使用动态代理将HTTP请求转换为Java方法的调用。

注解

在 Android 开发中,注解是一种非常常见的技术。注解(Annotation)是一种将元数据附加到代码中的方式,可以帮助编译器和开发者更好地理解代码的含义和用途,从而提高代码的可读性和可维护性。

在 Java 中,注解本质上是一种特殊的接口,被定义为 @interface。定义一个注解时,可以为其定义多个成员变量,这些成员变量可以设置默认值。注解还可以被标记为运行时可见或编译时可见。在代码中使用注解时,需要在注解名称前加上 @ 符号,并将注解放置在要注解的代码上方。例如,以下是一个简单的注解示例:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {
    String value() default "default value";
}

@MyAnnotation(value = "test value")
public class MyClass {
    // 通过反射取到自定义的注解对象。
    MyAnnotation annotation = clazz.getAnnotation(MyAnnotation.class);
}

在上面的代码中,我们定义了一个名为 MyAnnotation 的注解,它包含一个名为 value 的成员变量,并且设置了默认值为 "default value"。我们还使用了 @Retention@Target 注解,分别指定注解的保留策略和使用范围。最后,我们在 MyClass 类前使用了 @MyAnnotation 注解,并将 value 参数设置为 "test value"

以下是一些常用的场景:

  1. 提供元数据:通过注解可以为类、方法、字段等元素添加元数据信息,这些元数据可以在运行时被读取和使用。

  2. 配置类:通过注解可以简化配置文件的编写,比如通过注解来指定某个类或方法的特定配置信息。

  3. 编译时检查:通过自定义注解来进行编译时的检查,比如在 Android 开发中,通过注解来检查代码中是否存在可能导致内存泄漏的情况。

  4. 自动化代码生成:通过注解可以实现自动化代码生成,比如通过注解来生成数据库表的 CRUD 操作代码。

  5. 运行时处理:通过注解可以在运行时动态地处理类、方法、字段等元素,比如在 Android 开发中,通过注解来实现自动化的视图绑定。

动态代理

  • 动态代理是一种编程技术,它能够在运行时动态地创建一个实现了指定接口的代理类,这个代理类会拦截接口方法的调用并进行相应的处理。

  • 动态代理的实现方式通常是通过 Java 的反射机制来实现。当我们使用动态代理创建代理类时,Java 会动态生成一个代理类的字节码,并将这个代理类加载到 JVM 中。当客户端调用代理类的接口方法时,代理类会将方法调用转发给一个指定的处理器对象(InvocationHandler),处理器对象会根据需要对方法调用进行处理,并将结果返回给客户端。

  • 动态代理的应用场景比较广泛,比如在 AOP(面向切面编程)中,我们可以使用动态代理来实现对目标类方法的拦截和增强;在 RPC(远程过程调用)中,我们可以使用动态代理来将本地的方法调用转化为远程调用等。

通过这种方式,开发人员可以通过定义简单的接口来轻松地使用Web服务,而无需担心底层HTTP细节。此外,Retrofit还提供了许多其他功能,例如对异步操作的支持、数据转换和错误处理等,这使得与Web服务的交互更加容易和高效。


以下是常用的 Retrofit 方法:

  1. @GET:用于指定请求方法为 GET。
  2. @POST:用于指定请求方法为 POST。
  3. @PUT:用于指定请求方法为 PUT。
  4. @DELETE:用于指定请求方法为 DELETE。
  5. @Path:用于指定 URL 中的动态参数,例如 users/{userId}
  6. @Query:用于指定查询参数,例如 search?query=Android
  7. @Body:用于指定请求体的内容。
  8. @Headers:用于指定请求头。
  9. @FormUrlEncoded:用于指定表单编码的请求体。
  10. @Multipart:用于指定多部分表单的请求体。
  11. Call:用于发起异步请求。
  12. enqueue:用于异步请求的回调。
  13. execute:用于同步请求。
  14. ConverterFactory:用于指定数据转换器。
  15. Interceptor:用于指定拦截器,可以在请求和响应中添加额外的处理逻辑。

以下是一个使用 Retrofit 发起 GET 请求的简单示例:

public interface ApiService {
    @GET("users/{userId}/repos")
    Call<List<Repo>> listRepos(@Path("userId") String userId);
}

// 创建 Retrofit 实例
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://api.github.com/")
        .addConverterFactory(GsonConverterFactory.create())
        .build();

// 创建 API 接口的实例
ApiService apiService = retrofit.create(ApiService.class);

// 发起异步请求
Call<List<Repo>> call = apiService.listRepos("octocat");
call.enqueue(new Callback<List<Repo>>() {
    @Override
    public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {
        List<Repo> repos = response.body();
        // 处理响应数据
    }

    @Override
    public void onFailure(Call<List<Repo>> call, Throwable t) {
        // 处理请求失败的情况
    }
});

在这个示例中,我们定义了一个名为 ApiService 的接口,并使用 @GET@Path 注解来定义请求的 URL。然后,我们使用 Retrofit 创建了 ApiService 接口的实例,并使用 listRepos 方法发起了异步请求。

Retrofit 的几个高级功能:

  1. 支持自定义 Converter

Retrofit 内置了 Gson 和 Jackson 两个 JSON 解析库,但是如果我们需要支持其他格式的数据解析,比如 XML、Protobuf 等,可以通过实现自定义 Converter 来实现。自定义 Converter 需要实现 Converter.Factory 接口,并在 Retrofit.Builder 中注册。

举个例子,如果我们需要支持 XML 数据解析,可以通过如下代码来实现:

public class XmlConverterFactory extends Converter.Factory {
    public static XmlConverterFactory create() {
        return new XmlConverterFactory();
    }

    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
        return new XmlResponseBodyConverter<>();
    }

    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
        return new XmlRequestBodyConverter<>();
    }
}

public class XmlResponseBodyConverter<T> implements Converter<ResponseBody, T> {
    @Override
    public T convert(ResponseBody value) throws IOException {
        // 在这里实现 XML 解析逻辑
        return null;
    }
}

public class XmlRequestBodyConverter<T> implements Converter<T, RequestBody> {
    @Override
    public RequestBody convert(T value) throws IOException {
        // 在这里实现 XML 序列化逻辑
        return null;
    }
}

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://api.example.com/")
        .addConverterFactory(XmlConverterFactory.create())
        .build();

  1. 支持 RxJava

Retrofit 可以和 RxJava 集成,使我们可以在发起 HTTP 请求时使用 RxJava 的链式调用方式,提高代码的可读性和灵活性。通过调用 Retrofit 的 .create() 方法,我们可以创建一个支持 RxJava 的 Retrofit 实例,如下所示:

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://api.example.com/")
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
        .build();

然后我们就可以在请求接口时使用 RxJava 的 Observable 或 Single,如下所示:

public interface ApiService {
    @GET("users/{user}/repos")
    Single<List<Repo>> listRepos(@Path("user") String user);
}

ApiService apiService = retrofit.create(ApiService.class);

apiService.listRepos("octocat")
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new SingleObserver<List<Repo>>() {
            @Override
            public void onSubscribe(Disposable d) {
                // 在这里处理订阅事件
            }

            @Override
            public void onSuccess(List<Repo> repos) {
                // 在这里处理请求成功事件
            }

            @Override
            public void onError(Throwable e) {
                // 在这里处理请求失败事件
            }
        });

posted @ 2023-03-18 00:31  懒懒初阳  阅读(202)  评论(0编辑  收藏  举报