简介
Retrofit2是square公司开源的网络库,该公司的另一个库Okhttp,相信大家应该同样熟悉,在Retrofit流行之前,Okhttp是我们使用比较多的几个网络库之一。Retrofit虽然时下最流行,其实并没有替代Okhttp,Retrofit默认还是基于Okhttp去完成底层网络处理的,只是在上层做了进一步的封装,使开发者更易使用而已。本篇我们就来谈一谈Retrofit2的使用。
示例引入
添加依赖
dependencies {
compile 'com.squareup.retrofit2:retrofit:2.0.2'
}
Retrofit实例化
最基本的Retrofit创建:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://localhost:6666/")
.build();
接口定义
使用@GET定义了一个查询接口:
public interface AdsService {
@GET("ads")
Call<ResponseBody> getAds();
}
接口调用
调用getAds接口,并设置监听回调:
Call<ResponseBody> call = service.getAds();
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很重要的一个特色就是,使用注解配置网络参数,非常方便和优雅。
注解可以分为三类:
1、HTTP请求方法类
POST、DELETE、PUT、GET、HEAD、PATCH、OPTIONS、HTTP
下面以常用的GET、POST方法,以及比较特殊的HTTP注解为例来说明。
GET
@GET("ads")
Call<ResponseBody> getAds();
POST
@POST("login")
@FormUrlEncoded
Call<ResponseBody> login(@Field("username") String name, @Field("password") String pwd);
HTTP
HTTP可以替换其他7个注解使用:
@HTTP(method = "GET", path = "ads", hasBody = false)
Call<ResponseBody> getAds();
2、标记类
FormUrlEncoded
表示请求提是一个form表单,和Field、FieldMap配合使用
Multipart
表示请求体是一个支持文件上传的form表单,和Part、PartMap配合使用
Streaming
表示响应体的数据用流的形式返回
3、参数类
用于方法
这里就一个注解:Headers
@GET("ads")
@Headers({"headerName1: headerValue1", "headerName2: headerValue2"})
Call<ResponseBody> getAds();
用于方法参数
Path
@HTTP(method = "GET", path = "ads/{id}", hasBody = false)
Call<ResponseBody> getAd(@Path("id") int id);
Url
@GET
Call<ResponseBody> getAd(@Url String url, @Query("id") int id);
注:使用了Url注解,请求方法中就无需配置url参数了
Query和QueryMap
@GET("ads")
Call<ResponseBody> getAd(@Query("id") int id);
@GET("ads")
Call<ResponseBody> getAds(@QueryMap Map<String, String> map);
Field和FieldMap
@POST("login")
@FormUrlEncoded
Call<ResponseBody> login(@Field("username") String name, @Field("password") String pwd);
//或者写成这样
@POST("login")
@FormUrlEncoded
Call<ResponseBody> login(@QueryMap Map<String, String> map);
Header
@GET("ads")
Call<ResponseBody> getAds(@Header("headerName") String headerValue);
Part和PartMap
@POST("upload")
@Multipart
Call<ResponseBody> uploadFile1(@Part("name") RequestBody name, @Part MultipartBody.Part file);
@POST("upload")
@Multipart
Call<ResponseBody> uploadFile2(@PartMap Map<String, RequestBody> args, @Part MultipartBody.Part file);
使用Converter
这里只以常用的GsonConverter为例
添加converter-gson库依赖
dependencies {
compile 'com.squareup.retrofit2:converter-gson:2.0.2' //gson转换器,将JSON数据映射为对象
compile 'com.google.code.gson:gson:2.2.4' //Gson解析库
}
添加GsonConverterFactory
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.client(builder.build())
.addConverterFactory(GsonConverterFactory.create())//请求的结果转为实体类
.build();
接口修改
public interface AdsService {
@GET("ads")
Call<AdResult> getAds();
}
这里的AdResult对应JSON映射的对象
接口调用
Call<AdResult> call = service.getAds();
call.enqueue(new Callback<AdResult>() {
@Override
public void onResponse(Call<AdResult> call, Response<AdResult> response) {
if (response != null && response.isSuccessful()) {
}
}
@Override
public void onFailure(Call<AdResult> call, Throwable t) {
}
});
使用CallAdapter
这里只以常用的RxJava2CallAdapter为例
添加RxJava依赖
dependencies {
compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0' //RxJava2CallAdapter
compile 'io.reactivex.rxjava2:rxjava:2.1.3'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
}
添加RxJava2CallAdapterFactory
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.client(builder.build())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
接口修改
public interface AdsService {
@GET("ads")
Flowable<Response<AdResult>> getAds();
}
这里的Response是retrofit2.Response,便于获取Response状态信息。
接口调用
Flowable<Response<AdResult>> flowable = service.getAds();
flowable.map(new Function<Response<AdResult>, List<Ad>>() {
@Override
public List<Ad> apply(Response<AdResult> retrofitResponse) throws Exception {
if (retrofitResponse != null && retrofitResponse.isSuccessful()) {
return list;
}
return null;
}
}).subscribeOn(SchedulerProvider.getInstance().io())
.observeOn(SchedulerProvider.getInstance().ui())
.subscribe(new DefaultSubscriber<List<Ad>>() {
@Override
public void onNext(List<Ad> ads) {
}
@Override
public void onError(Throwable t) {
}
@Override
public void onComplete() {
}
});
添加Interceptor
日志Interceptor
如果使用了gson解析,打印网络请求和响应的日志,就没那么方便了,实际的网络操作都被封装起来了。我们需要使用squareup提供的另一个库来满足打印日志的需求,所以还要添加logging-interceptor库依赖。
添加依赖
dependencies {
compile 'com.squareup.okhttp3:logging-interceptor:3.6.0' //日志拦截器
}
设置Interceptor
private Api() {
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.readTimeout(30, TimeUnit.SECONDS)
.connectTimeout(30, TimeUnit.SECONDS)
.retryOnConnectionFailure(true);
if (BuildConfig.DEBUG) {
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new AdsLogger());
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);
builder.addInterceptor(loggingInterceptor);
}
...
}
private static class AdsLogger implements HttpLoggingInterceptor.Logger {
@Override
public void log(String message) {
Log.i("RetrofitLog", "" + message);
}
}
这里,我们可以通过BuildConfig.DEBUG控制是否支持日志打印。
总结
以上大概就是本人目前学习Retrofit2的一点心得,谈不上深入,也没有具体到项目,只能算是入门教程,存在错误的地方,希望指正。
参考资料
你真的会用Retrofit2吗?Retrofit2完全教程
Retrofit打印请求地址和返回内容
Retrofit — Getting Started and Creating an Android Client