Retrofit

Retrofit 是Square公司推出的简化HTTP请求的第三方库, 是对其公司另一网络请求库OkHttp的封装

实现了对响应数据解析的封装, 可以不需要自己去解析网络请求回来的数据. 使用方法采用注解的形式.

想要了解Retrofit的使用, 需要先了解Okhttp的用法. 因为Retrofit是基于Okhttp的封装. 同样也可以用Okhttp的方法.

参考文档:

官方

博客

演示

这里我以获取网站内容为例子

完整接口链接

http://liangjingkanji.coding.me/2017/03/03/TabLayout/

添加依赖

建议以官方GitHub最新版为准

compile 'com.squareup.retrofit2:retrofit:2.2.0'

创建实例

通过Retrofit的构造器创建实例对象

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://liangjingkanji.coding.me/") 
        .build();
  • baseUrl 一般存放的是服务器的域名, 记住必须以”/”结尾, 否则报异常

注意: 在Retrofit2版本以前baseUrl通过加不加”/”来判断@Path是绝对路径还是相对路径. 但是在2.0强制要求必须以”/”结尾.

创建接口

在Retrofit中每个接口都对应一个网络请求, 该接口是用于设置请求的参数或者路径以及响应体类型

public interface BlogService {

    @GET("2017/03/03/{index}") 
    Call<ResponseBody> getBlog(@Path("index") String index); 
}
  • @GET(“2017/03/03/{index}”) 表示以GET方式请求链接. 后面的字符串是拼接地址. “{}”大括号内部是占位符的含义. 最终会用getBlog里面的参数替代.
  • @Path(“index”) 表示其修饰的参数String index 将会替代之前提到的占位符”{index}”

创建服务

通过接口的字节码创建服务

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

执行回调

通过接口的方法得到回调

Call<ResponseBody> call = service.getBlog(2); // 得到回调

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(); // 打印请求错误异常信息
    }
});

全部请求方法

retrofit支持六种请求方式, 通过注解的方式使用. 上面的示例我们就使用了@GET 注解

  • GET
  • POST
  • PUT
  • DELETE
  • HEAD
  • OPTIONS
  • HTTP

其中HTTP是以通过值来决定请求方式的注解

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

这里我只讲解常用的GET和POST请求方式

GET请求

关键注解: @GET

可选参数: String path 表示一个绝对或者相对/完整的URL路径

这里请求方式注解的参数虽然说都是可选参数, 但是如果你完全不写还是会报错的. 除非你在服务接口的方法参数里面加个@URL 注解指定了路径.

如果你想直接用baseUrl的路径可以使用@GET("/")或者@GET(".")代表使用baseUrl作为完整路径. POST请求方式同样处理.

URL拼接

GET请求本身就是拼接URL. 所以你可以在路径里面直接写请求参数.

@GET("users/list?sort=desc")

如果在想传入值的情况下可以使用以下注解

关键注解 @Query 用于修饰方法参数

必须参数: String value 参数名

可选参数: boole encoded 是否对参数进行URLEncode编码

这里我没有把接口的路径写到@GET注解里面. 这种写法和之前示例里面的一样.

public interface GitHubService {
    @GET
    Call<String> request(@Query("key") String value @URL String path);
}

如果是参数名相同值不同的多个参数可以用可变参数写. 这算是数组类型参数.

后面这种可变参数的写法我不会再提.

 @GET
 Call<ResponseBody> list(@Query("category") String... categories, @URL String path);

结果

路径/list?category=bar&category=baz.

如果GET是多个参数一个个写是很麻烦的. 所以需要使用到Map集合

关键注解: @QueryMap 修饰Map集合

可选参数: boolean encoded 是否对参数进行URLEncode编码

 @GET("/search")
 Call<ResponseBody> list(@QueryMap Map<String, String> filters);

结果

路径 /search?foo=bar&kit=kat.

**注:**URLEncode编码是对URL地址中的特殊字符进行编码. 防止被服务器错误识别. 例如”&”默认为参数拼接的含义. 如果请求参数中包含这个特殊字符怎么办? URLEcode就会将其换成其他字符. 详情可以Google.

POST请求

关键注解: @POST

可选参数: String path 绝对或者相对/完整的URL路径

下面我会介绍Post请求的几种请求方式. 可以归纳为:

  1. 表单
  2. 字符串

FormUrl提交

即最常见的表单提交. 用于提交键值对的基本类型的参数. 注意不能上传文件. 也就是说@Field只能修饰基本数据类型.

关键注解: @FormUrlEncoded

@POST("/form")
@FormUrlEncoded
Call<ResponseBody> testFormUrlEncoded1(@Field("username") String name, @Field("age") int age);
单参数

POST请求肯定是要带有参数的. POST参数注解和GET参数注解类似

关键注解: @Field

必须参数: String value 表单参数的名字

可选参数: boolean encoded 是否对参数进行URLEncode编码

 @FormUrlEncoded
 @POST("/")
 Call<ResponseBody> example(
     @Field("name") String name,
     @Field("occupation") String occupation);
多参数

使用Map集合参数提交

关键注解: @FieldMap

可选参数: boolean encoded 是否对参数进行URLEncode编码

 @FormUrlEncoded
 @POST("/things")
 Call<ResponseBody> things(@FieldMap Map<String, String> fields);

Multipart提交

多类型提交一般用于文件. 也可以作为表单提交键值对

关键注解: @Multipart

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

关键注解: @Part

可选参数:

  • String value 参数名
  • String encoding
@POST("/form")
@Multipart
Call<ResponseBody> testFileUpload2(@Part MultipartBody.Part file);
多参数

关键注解: @PartMap

可选参数: String encoding

 @Multipart
 @POST("/upload")
 Call<ResponseBody> upload(
     @Part("file") RequestBody file,
     @PartMap Map<String, RequestBody> params);

关键注解: @Multipart

流类型提交

关键注解: @Streaming

请求参数

除了上面所提到的提交参数意外还有

路径拼接

GET注解后面一般不是都会有个相对路径的字符串嘛. 这个字符串里面可以通过写{}包裹任意内容. 被包裹的都是占位符. 最终会被Path注解修饰的参数替代. 最开始的示例就是用了这个注解.

关键注解: @Path

interface GitHubService { 
@GET("/repos/{owner}/{repo}/contributors")

List<Contributor> repoContributors( 
      @Path("owner") String owner, 
      @Path("repo") String repo
);
}

请求体

使用一个对象作为请求体提交, 例如使用Json进行参数的提交. 该请求体同样可以作为@GET请求的参数提交.

关键注解: @Body

@POST("users/new")
Call<User> createUser(@Body User user);

这个Body修饰的参数要求必须是Retrofit指定的响应体转换类型. 也就是说要求请求体和响应体都要求同样. 否则只能用Response作为请求体.

请求头

单请求头

关键注解: @Header

必须参数: String value 请求头参数

 @GET("/")
 Call<ResponseBody> foo(@Header("Accept-Language") String lang);
多请求头

使用String[] 作为请求头. 注意只有@Headers可以单独使用. 其他的请求头注解都只能修饰方法参数

关键注解: @Headers

必须参数: String[] value 请求头参数

单请求头

 @Headers("Cache-Control: max-age=640000")
 @GET("/")

多请求头

 @Headers({
   "X-Foo: Bar",
   "X-Ping: Pong"
 })
 @GET("/")

还可以使用Map集合作为请求头参数

关键注解: @HeaderMap

 @GET("/search")
 void list(@HeaderMap Map<String, String> headers);

Response 响应参数

关键类: Response

public static <T> Response<T> success(T body)

public static <T> Response<T> success(T body,
                                      okhttp3.Headers headers)

public static <T> Response<T> success(T body,
                                      okhttp3.Response rawResponse)

public static <T> Response<T> error(int code,
                                    okhttp3.ResponseBody body)

public static <T> Response<T> error(okhttp3.ResponseBody body,
                                    okhttp3.Response rawResponse)

public okhttp3.Response raw()

// 状态码
public int code()

// 响应消息, 如果未知返回null
public String message()

public okhttp3.Headers headers()

// 是否成功, 状态码在200~300之间([200..300))
public boolean isSuccessful()

// 得到响应体, 该响应体属于泛型, 详情介绍看Retrofit转换器
public T body()

// 访问失败返回的响应体, 即状态码不在200~300之间
public okhttp3.ResponseBody errorBody()

转换器

前面提过Retrofit支持直接返回你想要的类型对象. 例如返回的Json数据直接返回JsonBean对象. 而不是Response对象. 同样你想直接返回String类型也行.

除了添加Retrofit依赖外, 还需要添加转换响应体的依赖包. 官方提供六种常用转换库

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
Scalars (primitives, boxed, and String): com.squareup.retrofit2:converter-scalars

这里我使用了Gson转换器进行讲解

关键类

Gson

添加Gson转换器的依赖, 这里的依赖包版本号跟随Retrofit即可

compile 'com.squareup.retrofit2:converter-gson:2.2.0'

创建接口. “.”的路径表示使用baseUrl作为完整路径. 这里的TimeBean是我创建的一般的JsonBean类

public interface InterfaceService {
    @GET(".")
    Call<TimeBean> getServerTime();
}

创建实例的时候增加一个方法addConverterFactory

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("http://mob.mgtvshop.com/interface/get_time/")
    .addConverterFactory(GsonConverterFactory.create()) // 添加转换器
    .build();

InterfaceService service = retrofit.create(InterfaceService.class);
Call<TimeBean> serverTime = service.getServerTime();

serverTime.enqueue(new Callback<TimeBean>() {
  @Override
  public void onResponse(Call<TimeBean> call, Response<TimeBean> response) {

        // response的body()将直接返回Jsonbean类
    System.out.println(response.body().getMsg()); 

  }

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

  }
});

注:如果返回的Json不能被解析. 则返回null. 报空指针异常. 建议进行异常捕捉.

Retrofit

Build

public Retrofit.Builder baseUrl(okhttp3.HttpUrl baseUrl)

// 字符串链接必须以 "/"结尾, 一般为域名
public Retrofit.Builder baseUrl(String baseUrl)

// 设置一个Okhttp客户端
public Retrofit.Builder client(okhttp3.OkHttpClient client)

// 设置回调实例
public Retrofit.Builder callFactory(okhttp3.Call.Factory factory)

// 添加序列化或反序列化转换器
public Retrofit.Builder addConverterFactory(Converter.Factory factory)

public Retrofit.Builder addCallAdapterFactory(CallAdapter.Factory factory)

public Retrofit.Builder callbackExecutor(Executor executor)

public Retrofit.Builder validateEagerly(boolean validateEagerly)

public Retrofit build()

Retrofit

public <T> T create(Class<T> service)

请求网络

和Okhttp不同的是Retrofit的回调方法都已在主线程内. 可以直接更新UI.

Call

该方法和okHttp的Call类没什么区别.

同步执行

注意, Android不支持同步网络请求. 如果要使用需要处理 NetworkOnMainThreadException 异常

Response<T> execute()
             throws IOException

示例:

try {
          Response<ResponseBody> bodyResponse = call.execute();
          String body = bodyResponse.body().string();//获取返回体的字符串
          Log.i("wxl", "body=" + body);
      } catch (IOException e) {
          e.printStackTrace();
      }
异步执行
void enqueue(Callback<T> callback)

示例:

call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Response<ResponseBody> response) {
                try {
                    Log.i("wxl", "response=" + response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            @Override
            public void onFailure(Throwable t) {
                Log.i("wxl", "onFailure=" + t.getMessage());
            }
        });
更多方法
// 是否执行了网络请求
boolean isExecuted()

// 取消网络请求
void cancel()

// 是否执行了取消网络请求
boolean isCanceled()

// 创建新的网络请求
Call<T> clone()

// 得到请求对象
okhttp3.Request request()
网络请求的回调
Interface Callback<T>

实现接口需要重写两个方法:

成功:

void onResponse(Call<T> call,
                Response<T> response) // 成功时返回的响应体

失败:

该失败指的是服务器错误或者因为异常请求的原因. 例如Json解析错误也会回调该方法

void onFailure(Call<T> call,
               Throwable t) // 失败时抛出的异常
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值