Retrofit简单使用

本文详细介绍了Retrofit的基础用法,包括@GET、@POST等注解的使用,以及@Query、@Field、@Header等参数传递方式。同时,讨论了同步和异步请求的执行,展示了创建Retrofit对象、定义接口和处理结果的步骤。此外,提到了Retrofit的@Http注解以及如何与RxJava结合使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Retrofit学习笔记

Retrofit基础

  1. Retrofit 中使用注解的方式来区分请求类型,比如@GET("/record")表示一个GET请求,要以 / 开头,会拼接到基本URL后面,record为接口地址。各个格式和含义如下:
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZeC7NRhR-1588412613915)(http://note.youdao.com/yws/res/3591/96266863020D44CB8C19005FFDCE4B5A)]

例如,GET请求(其他请求类似):

 @GET("/apistore/mobilenumber/mobilenumber")           
  Call<PhoneResult> getResult(@Header("apikey") String apikey, @Query("phone") String phone);                              
  1. 服务器接口类型
  • 直接请求型
@GET("/record")             
Call<PhoneResult> getResult();

组合后直接请求

@GET("/result/{id}")         //其中{id}中的id在实际使用时填写实际值即可.
Call<PhoneResult> getResult(@Path("id") String id);
  • 带参查询型
@GET("/otn/lcxxcx/query")              //某个接口
Call<Result> query(@Query("purpose_codes") String codes);
  • 带Header型
@POST("/info")
Call<Object> updateInfo(@Header("device") String device, @Header("version") int version,
                        @Field("id") String id);
  1. 注解

1)、Query注解

interface QueryGET{
    @GET("/sheet")
    String getString(@Query("name")String name,@Query("age") int age);
    }  
  • query 访问的参数会添加到路径(path)的后面。encodeNames=true表示对url的query进行url编码,同理还有encodeValues. 这2个的值默认都是true。
  • 实际访问的地址是“http://tieba.baidu.com/sheet?name=xxx&age=xxx ”

2)、Field和Part注解
我们也可以在post请求的时候发送form-data和multipart-data.
表单数据要使用@FormUrlEncoded注解.每一对键值对都要用@Field进行注解, 包括名字和value对象的值.

@FormUrlEncoded
@POST("/user/edit")
User updateUser(@Field("first_name") String first, @Field("last_name") String last);

用@Multipart注解来发送multipart-data,每一个part用@part注解.


@Multipart
@PUT("/user/photo")
User updateUser(@Part("photo") TypedFile photo, @Part("description") TypedString description);

3)、Header注解
header分为key和value都固定,静态Header注解方法和动态Header注解方法。注意header不会相互覆盖。

  • 静态header
interface FixedHeader{
    @Headers({                                          //静态Header,先写好
        "Accept: application/vnd.github.v3.full+json",
        "User-Agent: Retrofit-Sample-App"
    })
    @GET("/")                     
    Response getResponse();    
}
  • 动态header
interface DynamicHeader{
    @Headers("Cache-Control: max-age=640000")             //静态Header
    @GET("/")
    Response getResponse(@Header("header1")String header1,@Header("header2")String header2);    //动态Header,其value值可以在调用这个方法时动态传入.
    }
  1. 同步和异步
  • 同步
    有返回值的方法是同步执行的,如:
interface Client{
@GET("/user/{id}/photo")
Photo getUserPhoto(@Path("id") int id);
}
  • 异步
    采用异步执行的话,需要方法的最后一个参数是CallBack且返回值类型是void
interface AsychronousClient{
    @GET("/")
    void getResponse(Callback<String> callback);  //如果使用异步的方式的话,特别注意这里方法的返回值必须是void,Response转化成的对象类型写在CallBack<T>的泛型中.
}

注意,异步方式的retrofit网络访问还是在子线程中运行的.但CallBack的success()和failure()方法是在主线程中运行的.(通过Android的Hanlder机制实现的)

Retrofit retrolfit = new Retrofit.Builder()
        .addConverterFactory(GsonConverterFactory.create())  //解析方法 用gson把ResponseBody转为我们泛型中的类型String
        .baseUrl(BASE_URL)
        .build();
AsychronousClient  create= retrolfit.create(AsychronousClient .class);
create.getResponse(new Callback<String>() {

    @Override
    public void onResponse(Call<String> call, Response<String> response) {
        
    }

    @Override
    public void onFailure(Call<String> call, Throwable t) {

    }
});
  1. 使用示例
  • 调用过程:

1.创建Retrofit对象

2.创建访问API的请求

3.发送请求

4.处理结果

public interface BlogService {
        @GET("blog/{id}") //这里的{id} 表示是一个变量
        Call<ResponseBody> getFirstBlog(@Path("id") int id);      /** 这里的id表示的是上面的{id} */ 
    }
public class Example01 {
    public static void main(String[] args) {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://localhost:4567/")
                .build();     //创建Retrofit对象
        BlogService service = retrofit.create(BlogService.class);
        Call<ResponseBody> call = service.getFirstBlog(2);          //创建访问API的请求
        // 用法和OkHttp的call如出一辙
        // 不同的是如果是Android系统回调方法执行在主线程
        call.enqueue(new Callback<ResponseBody>() {         //发送请求
            @Override
                //处理结果
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                try {
                    System.out.println(response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                t.printStackTrace();
            }
        });
    }
}
  1. Retrofit的22个注解详解
  • Http请求方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2uoINigv-1588412613919)(http://note.youdao.com/yws/res/3593/9554DCACBB9A4EFAB4BC6F12CCDCB09D)]

以上表格中的除HTTP以外都对应了HTTP标准中的请求方法,而HTTP注解则可以代替以上方法中的任意一个注解,有3个属性:method、path,hasBody,下面是用HTTP注解实现上面Example01.java 的例子。

public class Example02 {
    public interface BlogService {
        /**
         * method 表示请的方法,不区分大小写
         * path表示路径
         * hasBody表示是否有请求体
         */
        @HTTP(method = "get", path = "blog/{id}", hasBody = false)
        Call<ResponseBody> getFirstBlog(@Path("id") int id);
    }

    public static void main(String[] args) {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://localhost:4567/")
                .build();
        BlogService service = retrofit.create(BlogService.class);
        Call<ResponseBody> call = service.getFirstBlog(2);
        ResponseBodyPrinter.printResponseBody(call);
    }
}
  • 标记类

在这里插入图片描述

使用示例:

public class Example03 {
    public interface BlogService {

        /**
         * {@link FormUrlEncoded} 表明是一个表单格式的请求(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);

        /**
         * {@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);
    }

    public static void main(String[] args) {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://localhost:4567/")
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        BlogService service = retrofit.create(BlogService.class);

        // 演示 @FormUrlEncoded 和 @Field
        Call<ResponseBody> call1 = service.testFormUrlEncoded1("怪盗kidou", 24);
        ResponseBodyPrinter.printResponseBody(call1);
      
        // 演示 @FormUrlEncoded 和 @FieldMap
        // 实现的效果与上面想同
        Map<String, Object> map = new HashMap<>();
        map.put("username", "怪盗kidou");
        map.put("age", 24);
        Call<ResponseBody> call2 = service.testFormUrlEncoded2(map);
        ResponseBodyPrinter.printResponseBody(call2);

        //===================================================

        MediaType textType = MediaType.parse("text/plain");
        RequestBody name = RequestBody.create(textType, "怪盗kidou");
        RequestBody age = RequestBody.create(textType, "24");
        RequestBody file = RequestBody.create(MediaType.parse("application/octet-stream"), "这里是模拟文件的内容");

        // 演示 @Multipart 和 @Part
        MultipartBody.Part filePart = MultipartBody.Part.createFormData("file", "test.txt", file);
        Call<ResponseBody> call3 = service.testFileUpload1(name, age, filePart);
        ResponseBodyPrinter.printResponseBody(call3);

        //===================================================
        // 演示 @Multipart 和 @PartMap
        // 实现和上面同样的效果
        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);
    }
}
  • 注解类

在这里插入图片描述

@Body用于非表单请求,比如json请求,注解实体,然后添加Gson转换就会自动转成json格式数据。

public interface Api {
    //发送json数据形式的post请求,把网络请求接口的后半部分openapi/api/v2写在里面
    //Get是请求数据实体类,Take接受数据实体类
    @POST("openapi/api/v2") //Post请求发送数据
    Call<Take> request(@Body Ask ask);//@body即非表单请求体,被@Body注解的ask将会被Gson转换成json发送到服务器,返回到Take。 // 其中返回类型为Call<*>,*是接收数据的类
}

Headers/Header:

public interface BlogService {
        @GET("/headers?showAll=true")
        @Headers({"CustomHeader1: customHeaderValue1", "CustomHeader2: customHeaderValue2"})
        Call<ResponseBody> testHeader(@Header("CustomHeader3") String customHeaderValue3);
    }

其他用法在上面各个例子有涉及。

  1. 与RxJava结合使用(把call变成observable对象)
    1)、添加依赖
  compile 'io.reactivex:rxjava:x.y.z'
  compile 'io.reactivex:rxandroid:1.0.1'
  compile 'com.squareup.retrofit2:retrofit:2.0.2'
  compile 'com.squareup.retrofit2:converter-gson:2.0.2'
  compile 'com.squareup.retrofit2:adapter-rxjava:2.0.2'   //**新加的,结合使用需要**

2)、service接口

interface MyService {
  @GET("user/login" )
  Observable<UserInfo> login(          //注意返回是Observable!!!
          @Query("username") String username,
          @Query("password") String password
  );
}

3)、完成一个网络请求

 Retrofit retrofit = new Retrofit.Builder()
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())//**新的配置**
            .baseUrl(BASE_URL)
            .build();
      MyService service = retrofit.create(MyService.class);

      service.login(phone, password)               //获取Observable对象
              .subscribeOn(Schedulers.newThread())//请求在新的线程中执行
              .observeOn(Schedulers.io())         //请求完成后在io线程中执行
              .doOnNext(new Action1<UserInfo>() {
                  @Override
                  public void call(UserInfo userInfo) {
                      saveUserInfo(userInfo);//保存用户信息到本地
                  }
              })
              .observeOn(AndroidSchedulers.mainThread())//最后在主线程中执行
              .subscribe(new Subscriber<UserInfo>() {
                  @Override
                  public void onCompleted() {
                  }
                  @Override
                  public void onError(Throwable e) {
                      //请求失败
                  }
                  @Override
                  public void onNext(UserInfo userInfo) {
                      //请求成功                  }
              });

相关教程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Vinson武

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值