本文最后更新于:1 个月前

Retrofit 是一个 RESTful 的 HTTP 网络请求框架的封装,网络请求的工作本质上是由 OkHttp 完成,而 Retrofit 仅负责网络请求接口的封装。

1. 添加 Retrofit 库的依赖

//    将Java版本设置为1.8*或更高版本。不然会报错(java.lang.NoSuchMethodError: No static method metafactory...)
//    在android下添加
//    compileOptions {
//        sourceCompatibility JavaVersion.VERSION_1_8
//        targetCompatibility JavaVersion.VERSION_1_8
//    }
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'

2. 添加 Converters

Gson: com.squareup.retrofit2:converter-gson
Jackson: com.squareup.retrofit2:converter-jackson
Moshi: com.squareup.retrofit2:converter-moshi
Protobuf: com.squareup.retrofit2:converter-protobuf
Wire: com.squareup.retrofit2:converter-wire
Simple XML: com.squareup.retrofit2:converter-simplexml
JAXB: com.squareup.retrofit2:converter-jaxb
Scalars (primitives, boxed, and String): com.squareup.retrofit2:converter-scalars

3. 添加网络权限

<uses-permission android:name="android.permission.INTERNET"/>

4. 创建装载服务器返回数据的类

public class ResultData {
    ...
    // 根据返回数据的格式和数据解析方式(Json、XML等)定义
}

5. 创建用于配置网络请求的接口

Retrofit 将 Http 请求抽象成 Java 接口,采用注解描述网络请求参数和配置网络请求参数

public interface IGetRequest {
    @GET("getIpInfo.php?ip=59.108.54.37")
    Call<ResultData> getCall();
}

请求方法注解

  • @GET
  • @POST
  • @PUT
  • @DELETE
  • @HEAD(常用)

标记类注解

  • @FormUrlEncoded 表单请求
  • @Multipart 注解表示允许多个 @Part
  • @Streaming 代表响应的数据以流的形式返回,如果不适用它,则默认会把全部数据加载到内存,所以下载大文件时需要加上这个注解。

参数类注解

GET 请求访问网络
  • @Path 动态配置 URL 地址

    public interface IGetRequest {
        @GET("{path}/getIpInfo.php?ip=59.108.54.37")
        Call<ResultData> getCall(@Path("path") String path);
    }

    在 GET 注解中包含了 {path},它对应着 @Path 注解中的 "path",用来替换 GET 注解中的 {path} 的正是需要传入的 String path 的值。

  • @Query 动态指定查询条件

  • @QueryMap 动态指定查询条件组

POST 请求访问网络
  • @Field 传输数据类型为键值对

    public interface IGetRequest {
        @FormUrlEncoded
        @POST("getIpInfo.php")
        Call<IpModel> getIpMsg(@Field("ip") String first);
    }

    首先用 @FormUrlEncoded 注解来标明这是一个表单请求,然后在 getIpMsg 方法中使用 @Field 注解来标示所对应的 String 类型数据的键,从而组成一组键值对进行传递。

  • @Body 传输数据类型 JSON 字符串

    public interface IGetRequest {
        @POST("getIpInfo.php")
        Call<IpModel> getIpMsg(@Body Ip ip);
    }

    @Body 这个注解标识参数对象即可,Retrofit 会将 Ip 对象转换为字符串。

  • @Part 单个文件上传

    public interface UploadFileForPart {
        @Multipart
        @POST("user/photo")
        Call<User> updateUser(@Part MultipartBody.Part photo, @Part("description") RequestBody description);
    }

    @Multipart 注解表示允许多个 @PartupdateUser 方法的第一个参数是准备上传的图片文件,另一个参数是 RequestBody 类型,用来传递简单的键值对。

  • @PartMap 多个文件上传

    public interface UploadFileForPart {
        @Multipart
        @POST("user/photo")
        Call<User> updateUser(@PartMap Map<String, RequestBody> photos, @Part("description") RequestBody description);
    }

    其它和单文件上传类似,只是使用 Map 封装了上传的文件。

Header 消息报头

在 HTTP 请求中,为了防止攻击和过滤掉不安全的访问,或者添加特殊加密的访问,通常会在消息报头中携带一些特殊的消息头处理。Retrofit 提供了 @Header 来添加消息报头。添加消息报头有两种方式:一种是静态的,另一种是动态的。

静态方式
public interface SomeService {
    @GET("some/endpoint")
    @Headers("Accept-Encoding: application/json")
    Call<ResponseBody> getCarType();
}

使用 @Headers 注解添加消息报头。如果想要添加多个消息报头,可以使用 {} 包含起来:

@Headers({
    "Accept-Encoding: application/json",
    "User-Agent: MoonRetrofit"
})
动态方式
public interface SomeService {
    @GET("some/endpoint")
    Call<ResponseBody> getCarType(@Header("Location") String location);
}

详细解释见如下博文链接

6. 创建 Retrofit 实例

Retrofit 是通过建造者模式构建出来的。请求 URL 是拼接而成的,它是由 baseUrl 传入的 URL 加上请求网络接口的 @GET("getIpInfo.php?ip=59.108.54.37") 中的 URL 拼接而成的。

Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(Url)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build()

7. 创建网络请求接口实例

// 创建网络请求接口的实例
IGetRequest request = retrofit.create(IGetRequest.class);
// 对发送请求进行封装
Call<ResultData> call = request.getCall();

8. 发送网络请求(异步 or 同步), and 处理

//发送网络请求(异步)
call.enqueue(new Callback<ResultData>() {
    //请求成功时回调
    @Override
    public void onResponse(Call<ResultData> call, Response<ResultData> response) {
        //处理结果
    }

    //请求失败时候的回调
    @Override
    public void onFailure(Call<ResultData> call, Throwable throwable) {
        //提示失败
    }
});

// 发送网络请求(同步)
Response<ResultData> response = call.execute();

9. 中断网络请求

call.cancel()


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

安卓导航组件 上一篇
Markdown语法 下一篇