美文网首页
Retrofit在Android中使用

Retrofit在Android中使用

作者: 放羊娃华振 | 来源:发表于2019-11-28 13:10 被阅读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的使用就大致介绍完毕了!

    相关文章

      网友评论

          本文标题:Retrofit在Android中使用

          本文链接:https://www.haomeiwen.com/subject/vhfbwctx.html