Retrofit(一)

Retrofit(一)

一. Retrofit介绍

Retrofit基于Okhttp封装的网络请求框架,网络请求的工作本质上是 OkHttp 完成,而 Retrofit 仅负责网络请求接口的封装.

二. Retrofit简单使用

请求百度URL

1. 添加依赖

	implementation 'com.squareup.retrofit2:retrofit:2.2.0' 
    implementation 'com.squareup.retrofit2:converter-gson:2.0.2'
    implementation 'com.squareup.retrofit2:converter-scalars:2.3.0'

2. 添加权限


3. 创建请求接口

public interface BaiduInterface {

   	@GET("http://www.baidu.com")
    Call baidu();

}

4. 进行请求

Retrofit retrofit = new Retrofit.Builder()
    		//baseUrl必须以/结尾
            .baseUrl("http://www.baidu.com/")
    		//添加数据解析,此处解析为字符串类型
            .addConverterFactory(ScalarsConverterFactory.create())
    		//创建
            .build();

	//获取请求接口的实例
    BaiduInterface baiduInterface = retrofit.create(BaiduInterface.class);
	//调用请求方法
    Call<String> baidu = baiduInterface.baidu();
	//进行异步请求
    baidu.enqueue(new Callback<String>() {
        @Override
        public void onResponse(Call<String> call, Response<String> response) {
            Log.d("RETROFIT", "onResponse: " + response.body());
        }

        @Override
        public void onFailure(Call<String> call, Throwable t) {
            Log.d("RETROFIT", "onFailure: ");
        }
    });
}

请求结果
Retrofit(一)_第1张图片

三. Retrofit的注解

  • Retrofit注解共22个,根据功能大概能分为三大类
  • 请求方法类
    • GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、HTTP
  • 标记类
    • FormUrlEncoded、Multipart、Streaming
  • 参数类
    • Headers、Header、Body、Field、FieldMap、Part、PartMap、Query、QueryMap、Path、URL

3.1 请求方法类

GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS分别对应Http的网络请求方式。

每个注解后都可设置一个Url,或者不设置

public interface BaiduInterface {

    @GET("http://www.baidu.com")
    Call<String> baidu();
    //@GET:采用GET请求方式发送请求
    //Call String是请求返回的数据类型
    //baidu() 请求方法
}

HTTP

public interface BaiduInterface {

	//method 请求方法
	//path 路径
	//hasBody 是否有请求体
    @HTTP(method = "GET" ,path = "new/{id}",hasBody = false)
    Call<ResponseBody> getCall(@Path("id") int id);
    
    //url中可以使用变量,如{id},并使用@Path("id")注解为{id}赋值
}

关于Url

  • Retrofit将URL分为两个部分,一部分在接口的注解后,一部分在baseUrl中。
//第一部分:在网络请求方法的注解中设置
@GET("s?cl=3&tn=baidutop10&fr=top1000&wd=全明星致敬科比&rsv_idx=2&rsv_dl=fyb_n_homepage&hisfilter=1")
Call<String> baidu();
//第二部分:在baseUrl中
Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://www.baidu.com/")
                .addConverterFactory(ScalarsConverterFactory.create())
                .build();

网络请求的完整Url=在创建的Retrofit实例时通过baseUrl设置的+网络请求方法注释中设置的

网络请求方法的参数也可设置Url

@GET
Call<String> baidu(@Url String url);

3.2 标记类

FormUrlEncoded

  • 每个键都需要@Field注解,在随后的调用需要提供值
public interface RetrofitInterface{
    
    @POST()
    @FormUrlEncoded
    Call<ResponseBody> testFormUrlEncoded(@Field("username") String name,@Field("age") int age);
}

Multipart

  • 每个键都需要用@part来注解,随后调用需要提供值,适用于有文件上传的场景。
public interface RetrofitInterface{
    
    @POST()
    @Multipart
    Call<ResponseBody> testFileUpload(@Part("username") RequestBody name,@Part("age") RequestBody age,@Part MultipartBody.Part file);
}

Streaming

  • 表示返回的数据以流的形式返回
  • 大文件官方建议用@Streaming注解,不然会出现IO异常,小文件可以忽略不注入。如果想进行断点续传的话,可以在此加入header
public interface RetrofitInterface{
    
    @GET
    @FormUrlEncoded
    Observable<ResponseBody> downloadFile(@Url String url);
}

3.3 网络请求参数

  • @Headers

    • 添加请求头
    • 网络请求接口的方法
  • @Header

    • 添加不固定值的请求头
    • 参数列表
    // @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作用于方法
    
    
  • @Body

    • 用于非表单请求体,以Post方式传递自定义数据类型给服务器

    • 如果提交一个Map,那么作用相当于@Field,不过Map要经过FormBody.Builder类处理成为符合okhttp格式的表单

    • 参数列表

    • FormBody.Builder builder = new FormBody.Builder();
      builder.add("key","value");
      
      
  • @Field @FieldMap

    • 向POST表单传入键值对

    • 参数列表

    • 作用:发送Post请求时提交请求的表单字段,与@FormUrlEncoded注解配合使用

    • public interface RetrofitInterface {
          /**
           *表明是一个表单格式的请求(Content-Type:application/x-www-form-urlencoded)
           * Field("username") 表示将后面的 String name 中name的取值作为 username 的值
           */
          @POST("/form")
          @FormUrlEncoded
          Call<ResponseBody> testFormUrlEncoded1(@Field("username") String name, @Field("age") int age)}
      
      //具体使用
       Call<ResponseBody> call1 = service.testFormUrlEncoded1("Carson", 24);
      
      
    • public interface RetrofitInterface {
          /**
           *表明是一个表单格式的请求(Content-Type:application/x-www-form-urlencoded)
           * Field("username") 表示将后面的 String name 中name的取值作为 username 的值
           */
          @POST("/form")
          @FormUrlEncoded
          Call<ResponseBody>testFormUrlEncoded2(@FieldMap Map<String, Object> map);
      }
      
      //具体使用
         Map<String, Object> map = new HashMap<>();
         map.put("username", "Carson");
         map.put("age", 24);
         Call<ResponseBody> call2 = service.testFormUrlEncoded2(map);
      
      
  • @Part @PartMap

    • 用于表单字段,适用于有文件上传的情况

    • 参数列表

    • 与@Multipart配合使用

    • public interface RetrofitInterface {
              /**
               * {@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);
      }
      
      
              MediaType textType = MediaType.parse("text/plain");
              RequestBody name = RequestBody.create(textType, "Carson");
              RequestBody age = RequestBody.create(textType, "24");
              RequestBody file = RequestBody.create(MediaType.parse("application/octet-stream"), "这里是模拟文件的内容");
      //调用
              MultipartBody.Part filePart = MultipartBody.Part.createFormData("file", "test.txt", file);
              Call<ResponseBody> call3 = service.testFileUpload1(name, age, filePart);
              ResponseBodyPrinter.printResponseBody(call3);
      
      
    • public interface RetrofitInterface {
         
              /**
               * PartMap 注解支持一个Map作为参数,支持 {@link RequestBody } 类型,
               * 如果有其它的类型,会被{@link retrofit2.Converter}转换,如后面会介绍的 使用{@link com.google.gson.Gson} 的 {@link retrofit2.converter.gson.GsonRequestBodyConverter}
               * 所以{@link MultipartBody.Part} 就不适用了,所以文件只能用 @Part MultipartBody.Part 
               */
              @POST("/form")
              @Multipart
              Call<ResponseBody> testFileUpload2(@PartMap Map<String, RequestBody> args, @Part MultipartBody.Part file);
      }
      
      
              MediaType textType = MediaType.parse("text/plain");
              RequestBody name = RequestBody.create(textType, "Carson");
              RequestBody age = RequestBody.create(textType, "24");
              RequestBody file = RequestBody.create(MediaType.parse("application/octet-stream"), "这里是模拟文件的内容");
      //调用
              Map<String, RequestBody> fileUpload2Args = new HashMap<>();
              fileUpload2Args.put("name", name);
              fileUpload2Args.put("age", age);
              //这里并不会被当成文件,因为没有文件名(包含在Content-Disposition请求头中),但上面的 filePart 有
              //fileUpload2Args.put("file", file);
              Call<ResponseBody> call4 = service.testFileUpload2(fileUpload2Args, filePart); //单独处理文件
              ResponseBodyPrinter.printResponseBody(call4);
      
      
  • @Query @QueryMap

    • @Query和@QueryMap的数据体现在Url上
    • 参数列表
  • @Path

    • Url缺省值

    • 参数列表

    • @GET("group/{id}/users")
      Call<List<User>> groupList(@Path("id") int groupId);
      
      
  • @Url

    • Url设置

    • public interface RetrofitInterface {
          @GET
          Call<String> baidu(@Url String url);
      }
      
      

你可能感兴趣的:(Android)