Retrofit2是square公司开源的网络库,该公司的另一个库Okhttp,相信大家应该同样熟悉,在Retrofit流行之前,Okhttp是我们使用比较多的几个网络库之一。Retrofit虽然时下最流行,其实并没有替代Okhttp,Retrofit默认还是基于Okhttp去完成底层网络处理的,只是在上层做了进一步的封装,使开发者更易使用而已。本篇我们就来谈一谈Retrofit2的使用。
dependencies {
compile 'com.squareup.retrofit2:retrofit:2.0.2'
}
最基本的Retrofit创建:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://localhost:6666/")
.build();
使用@GET定义了一个查询接口:
public interface AdsService {
@GET("ads")
Call getAds();
}
调用getAds接口,并设置监听回调:
Call call = service.getAds();
call.enqueue(new Callback() {
@Override
public void onResponse(Call call, Response response) {
try {
System.out.println(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call call, Throwable t) {
t.printStackTrace();
}
});
Retrofit很重要的一个特色就是,使用注解配置网络参数,非常方便和优雅。
注解可以分为三类:
POST、DELETE、PUT、GET、HEAD、PATCH、OPTIONS、HTTP
下面以常用的GET、POST方法,以及比较特殊的HTTP注解为例来说明。
@GET("ads")
Call getAds() ;
@POST("login")
@FormUrlEncoded
Call login(@Field("username") String name, @Field("password") String pwd);
HTTP可以替换其他7个注解使用:
@HTTP(method = "GET", path = "ads", hasBody = false)
Call<ResponseBody> getAds();
表示请求提是一个form表单,和Field、FieldMap配合使用
表示请求体是一个支持文件上传的form表单,和Part、PartMap配合使用
表示响应体的数据用流的形式返回
这里就一个注解:Headers
@GET("ads")
@Headers({"headerName1: headerValue1", "headerName2: headerValue2"})
Call getAds() ;
@HTTP(method = "GET", path = "ads/{id}", hasBody = false)
Call<ResponseBody> getAd(@Path("id") int id);
@GET
Call getAd(@Url String url, @Query("id") int id) ;
注:使用了Url注解,请求方法中就无需配置url参数了
@GET("ads")
Call getAd(@Query("id") int id);
@GET("ads")
Call getAds(@QueryMap Map<String, String> map);
@POST("login")
@FormUrlEncoded
Call login(@Field("username") String name, @Field("password") String pwd);
//或者写成这样
@POST("login")
@FormUrlEncoded
Call login(@QueryMap Map map);
@GET("ads")
Call getAds(@Header("headerName") String headerValue) ;
@POST("upload")
@Multipart
Call uploadFile1(@Part("name") RequestBody name, @Part MultipartBody.Part file);
@POST("upload")
@Multipart
Call uploadFile2(@PartMap Map args, @Part MultipartBody.Part file);
这里只以常用的GsonConverter为例
dependencies {
compile 'com.squareup.retrofit2:converter-gson:2.0.2' //gson转换器,将JSON数据映射为对象
compile 'com.google.code.gson:gson:2.2.4' //Gson解析库
}
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.client(builder.build())
.addConverterFactory(GsonConverterFactory.create())//请求的结果转为实体类
.build();
public interface AdsService {
@GET("ads")
Call getAds();
}
这里的AdResult对应JSON映射的对象
Call call = service.getAds();
call.enqueue(new Callback() {
@Override
public void onResponse(Call call, Response response) {
if (response != null && response.isSuccessful()) {
}
}
@Override
public void onFailure(Call call, Throwable t) {
}
});
这里只以常用的RxJava2CallAdapter为例
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'
}
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.client(builder.build())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
public interface AdsService {
@GET("ads")
Flowable> getAds();
}
这里的Response是retrofit2.Response,便于获取Response状态信息。
Flowable> flowable = service.getAds();
flowable.map(new Function, List>() {
@Override
public List apply(Response retrofitResponse) throws Exception {
if (retrofitResponse != null && retrofitResponse.isSuccessful()) {
return list;
}
return null;
}
}).subscribeOn(SchedulerProvider.getInstance().io())
.observeOn(SchedulerProvider.getInstance().ui())
.subscribe(new DefaultSubscriber>() {
@Override
public void onNext(List ads) {
}
@Override
public void onError(Throwable t) {
}
@Override
public void onComplete() {
}
});
如果使用了gson解析,打印网络请求和响应的日志,就没那么方便了,实际的网络操作都被封装起来了。我们需要使用squareup提供的另一个库来满足打印日志的需求,所以还要添加logging-interceptor库依赖。
dependencies {
compile 'com.squareup.okhttp3:logging-interceptor:3.6.0' //日志拦截器
}
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