Retrofit在Android中使用

2019-11-28  本文已影响0人  放羊娃华振

一、介绍

Retrofit 是一个 RESTful(一种架构风格)的 HTTP 网络请求框架的封装。注意这里并没有说它是网络请求框架,主要原因在于网络请求的工作并不是Retrofit 来完成的。Retrofit2.0 内置 OkHttp,Retrofit 得益于 OkHttp 的优势,较之于 Volley 是一种更加先进的网络框架。
Retrofit 专注于接口的封装,OkHttp 专注于网络请求的高效,二者分工协作!
我们的应用程序通过 Retrofit 请求网络,实际上是使用 Retrofit 接口层封装请求参数、Header、Url 等信息,之后由 OkHttp 完成后续的请求操作,在服务端返回数据之后,OkHttp 将原始的结果交给 Retrofit,Retrofit 根据用户的需求对结果进行解析的过程。

二、使用步骤

1.添加Retrofit库的依赖:

implementation 'com.squareup.retrofit2:retrofit:2.0.2'
implementation 'com.squareup.retrofit2:converter-gson:2.0.2'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.squareup.retrofit2:adapter-rxjava:2.0.2'

后面三个是可选的,分别是数据解析器和gson,以及rxjava支持的依赖

2.创建 用于描述网络请求 的接口
Retrofit将 Http请求 抽象成 Java接口:采用 注解 描述网络请求参数 和配置网络请求参数

/**
 * @Description: 用户信息
 * @Author: dzh
 * @CreateDate: 2019/4/25 20:54
 */
public interface TestService {

    //获取测试接口信息
    @GET()
    Observable<Result<List<PublicEngModel>>> getNetData(@Url String url, @Header("checkCookie") boolean checkCookie);
}

3.创建Retrofit实例

  Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://test.com/") //设置网络请求的Url地址
                .addConverterFactory(GsonConverterFactory.create()) //设置数据解析器
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();

4.添加调用的API层

/**
 * @Description: 描述
 * @Author: dzh
 * @CreateDate: 2019-11-18 16:26
 */
public class TestServiceApi {
    TestService testService;

    @Inject
    public TestServiceApi(Retrofit retrofit) {
        testService = retrofit.create(TestService.class);
    }

    public Observable<Result<List<PublicEngModel>>> getNetData() {
        return testService.getNetData(BaseConfig.APP_DOMAIN + "/app/public/english", false).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }
}

5.发送请求
请求分为同步请求和异步请求

 @Override
    public void getNetData() {

        serviceApi.getNetData()
                .observeOn(AndroidSchedulers.mainThread())
                .compose(getView().<Result<List<PublicEngModel>>>getBindToLifecycle())
                .subscribe(new BaseRxObserver<Result<List<PublicEngModel>>>() {
                    @Override
                    protected void onError(ResponeThrowable e) {
                        mView.hideLoadingDialog();
                        getView().showToastMsg(e.message);
                    }

                    @Override
                    protected void onSuccess(Result<List<PublicEngModel>> response) {
//                        mView.hideLoadingDialog();
                        if (response.data != null) {
                            getView().onNetData(response.data);
                        }
                    }
                });

    }

上面是对代码的封装成功时走onSuccess(),失败的时候走onError()。

下图是传入URL规则的整合:

image.png

注解

Retrofit还提供了很多其他的注解类型,我们常用的是@GET注解来发送Get请求,@POST注解来发送POST请求。下面列举主要的注解标识:

image.png
1、网络请求方法
image.png

1.@GET、@POST、@PUT、@DELETE、@HEAD分别对应 HTTP中的网络请求方式
2.@HTTP替换@GET、@POST、@PUT、@DELETE、@HEAD注解的作用 及 更多功能拓展
具体使用:通过属性method、path、hasBody进行设置

public interface TestService {
    /**
     * method:网络请求的方法(区分大小写)
     * path:网络请求地址路径
     * hasBody:是否有请求体
     */
    @HTTP(method = "GET", path = "blog/{id}", hasBody = false)
    Call<ResponseBody> getTestData(@Path("id") int id);
    // {id} 表示是一个变量
    // method 的值 retrofit 不会做处理,所以要自行保证准确
}

2、标记
! image.png

1.@FormUrlEncoded
表示发送form-encoded的数据,每个键值对需要用@Filed来注解键名,随后的对象需要提供值。
2.@Multipart
表示发送form-encoded的数据(适用于 有文件 上传的场景),每个键值对需要用@Part来注解键名,随后的对象需要提供值。

public interface TestService {
        /**
         *表明是一个表单格式的请求(Content-Type:application/x-www-form-urlencoded)
         * <code>Field("username")</code> 表示将后面的 <code>String name</code> 中name的取值作为 username 的值
         */
        @POST("/form")
        @FormUrlEncoded
        Call<ResponseBody> testFormUrlEncoded1(@Field("username") String name, @Field("age") int age);

        /**
         * {@link Part} 后面支持三种类型,{@link RequestBody}、{@link okhttp3.MultipartBody.Part} 、任意类型
         * 除 {@link okhttp3.MultipartBody.Part} 以外,其它类型都必须带上表单字段({@link okhttp3.MultipartBody.Part} 中已经包含了表单字段的信息),
         */
        @POST("/form")
        @Multipart
        Call<ResponseBody> testFileUpload1(@Part("name") RequestBody name, @Part("age") RequestBody age, @Part MultipartBody.Part file);

}

3、网络请求参数
image.png

1.@Header & @Headers
添加请求头 &添加不固定的请求头

// @Header
@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)

// @Headers
@Headers("Authorization: authorization")
@GET("user")
Call<User> getUser()

// 以上的效果是一致的。
// 区别在于使用场景和使用方式
// 1\. 使用场景:@Header用于添加不固定的请求头,@Headers用于添加固定的请求头
// 2\. 使用方式:@Header作用于方法的参数;@Headers作用于方法

2.@Body
以 Post方式 传递 自定义数据类型 给服务器,如果提交的是一个Map,那么作用相当于 @Field,不过Map要经过 FormBody.Builder 类处理成为符合 Okhttp 格式的表单,如:

FormBody.Builder builder = new FormBody.Builder();
builder.add("key","value");

3.@Field & @FieldMap
发送 Post请求 时提交请求的表单字段,与 @FormUrlEncoded 注解配合使用

 public interface TestService {
        /**
         * 表明是一个表单格式的请求(Content-Type:application/x-www-form-urlencoded)
         * <code>Field("username")</code> 表示将后面的 <code>String name</code> 中name的取值作为 username 的值
         */
        @POST("/form")
        @FormUrlEncoded
        Call<ResponseBody> testFormUrlEncoded1(@Field("username") String name, @Field("age") int age);

        /**
         * Map的key作为表单的键
         */
        @POST("/form")
        @FormUrlEncoded
        Call<ResponseBody> testFormUrlEncoded2(@FieldMap Map<String, Object> map);

    }

4.@Part & @PartMap
发送 Post请求 时提交请求的表单字段,与@Field的区别:功能相同,但携带的参数类型更加丰富,包括数据流,所以适用于 有文件上传 的场景,与 @Multipart 注解配合使用

public interface TestService {

        /**
         * {@link Part} 后面支持三种类型,{@link RequestBody}、{@link okhttp3.MultipartBody.Part} 、任意类型
         * 除 {@link okhttp3.MultipartBody.Part} 以外,其它类型都必须带上表单字段({@link okhttp3.MultipartBody.Part} 中已经包含了表单字段的信息),
         */
        @POST("/form")
        @Multipart
        Call<ResponseBody> testFileUpload1(@Part("name") RequestBody name, @Part("age") RequestBody age, @Part MultipartBody.Part file);

        /**
         * PartMap 注解支持一个Map作为参数,支持 {@link RequestBody } 类型,
         * 如果有其它的类型,会被{@link retrofit2.Converter}转换,如后面会介绍的 使用{@link com.google.gson.Gson} 的 {@link retrofit2.converter.gson.GsonRequestBodyConverter}
         * 所以{@link MultipartBody.Part} 就不适用了,所以文件只能用<b> @Part MultipartBody.Part </b>
         */
        @POST("/form")
        @Multipart
        Call<ResponseBody> testFileUpload2(@PartMap Map<String, RequestBody> args, @Part MultipartBody.Part file);

        @POST("/form")
        @Multipart
        Call<ResponseBody> testFileUpload3(@PartMap Map<String, RequestBody> args);
    }

5.@Query和@QueryMap
用于 @GET 方法的查询参数(Query = Url 中 ‘?’ 后面的 key-value)如:url = [http://www.test.com/?type=android]=其中,Query = type配置时只需要在接口方法中增加一个参数即可:

   @GET("/")    // 其使用方式同 @Field与@FieldMap,这里不作过多描述
   Call<String> cate(@Query("cate") String cate);
}

6.@Path
URL地址的缺省值

public interface TestService {
        @GET("users/{user}/repos")
        Call<ResponseBody>  getNetBlog(@Path("user") String user );
        // 访问的API是:https://api.test.com/users/{user}/repos
        // 在发起请求时, {user} 会被替换为方法的第一个参数 user(被@Path注解作用)
    }

7.@Url
直接传入一个请求的 URL变量 用于URL设置

public interface TestService {
        @GET
        Call<ResponseBody> testUrlAndQuery(@Url String url, @Query("showAll") boolean showAll);
       // 当有URL注解时,@GET传入的URL就可以省略
       // 当GET、POST...HTTP等方法中没有设置Url时,则必须使用 {@link Url}提供
}

至此Retrofit的使用就大致介绍完毕了!

上一篇下一篇

猜你喜欢

热点阅读