Retrofit 是安卓上最流行的HTTP Client库之一,Retrofit基于注解和动态代理,优化了Android中的网络请求操作。随着项目的深入,Retrofit开始深入学习,发现有必要将学习以及实践过程中的一些经验总结一下。
包的引用方式
包的引用方式没变,如果你想在自己的工程中导入Retrofit2.0,只需将你的gradle脚本中Retrofit依赖一行的版本号改为2.0以后即可(切记:Android Studio环境需要重启哦)
compile 'com.squareup.retrofit2:retrofit:2.0.0'
同步和异步定义以及执行方式
Retrofit1.0版本中,如果你想定义一个同步或者异步函数,你应该这样定义:
具有返回值的函数为同步执行的。
@GET("/user/{id}/photo")
Photo listUsers(@Path("id") int id);
而异步执行函数没有返回值并且要求函数最后一个参数为Callback对象
@GET("/user/{id}/photo")
void listUsers(@Path("id") int id, Callback cb);
但是在Retrofit 2.0上,只需定义一个模式,因此要简单得多。
@POST("/list")
Call loadRepo();
同步调用:
Call call=service.loadRepo();
Repo repo=call.execute();
异步调用:
Call call=service.loadRepo();
call.enqueue(new Callback(){
@Override
public void onResponse(Response response){
}
@Override
public void onFailure(Throwable t){
}
});
取消正在进行的网络任务
Retrofit1对正在进行的网络任务无法取消,如果你想做这件事必须手动杀死,而这并不好实现。而Retrofit2接口的定时形式变化,正是为了解决这个问题。要做到这点,你只需要调用call.cancel即可
Converter现在从Retrofit中删除
Retrofit1中的setConverter,2.0换以addConverterFactory,用于支持Gson转换。
在Retrofit 1.9中,GsonConverter 包含在了package 中而且自动在RestAdapter创建的时候被初始化。这样来自服务器的son结果会自动解析成定义好了的Data Access Object(DAO)
但是在Retrofit 2.0中,Converter 不再包含在package 中了。你需要自己插入一个Converter 不然的话Retrofit 只能接收字符串结果。同样的,Retrofit 2.0也不再依赖于Gson 。
如果你想接收json 结果并解析成DAO,你必须把Gson Converter 作为一个独立的依赖添加进来。
compile 'com.squareup.retrofit:converter-gson:2.1.0'
然后使用addConverterFactory把它添加进来。注意RestAdapter的别名仍然为Retrofit。
Retrofit retrofit=new Retrofit.Builder()
.baseUrl("http://api.nuuneoi.com/base/")
.addConverterFactory(GsonConverterFactory.create())
.build();
自定义Gson对象
为了以防你需要调整json里面的一些格式,比如,Date Format。你可以创建一个Gson 对象并把它传递给GsonConverterFactory.create()。
Gson gson=new GsonBuilder()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
.create();
Retrofit retrofit=new Retrofit.Builder()
.baseUrl("http://api.nuuneoi.com/base/")
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
新的URL定义方式
对于 Retrofit 2.0中新的URL定义方式,这里是我的建议:
- Base URL: 总是以 /结尾
- @Url: 不要以 / 开头
而且在Retrofit 2.0中我们还可以在@Url里面定义完整的URL:
@POST("http://api.nuuneoi.com/special/user/list")
Call loadSpecialUsers();
这种情况下Base URL会被忽略。
可以看到在URL的处理方式上发生了很大变化。它和前面的版本完全不同。如果你想把代码迁移到Retrofit 2.0,别忘了修正URL部分的代码。
即使response存在问题onResponse依然被调用
在Retrofit 1.9中,如果获取的 response 不能背解析成定义好的对象,则会调用failure。但是在Retrofit 2.0中,不管 response 是否能被解析。onResponse总是会被调用。但是在结果不能被解析的情况下,response.body()会返回null。别忘了处理这种情况。
如果response存在什么问题,比如404什么的,onResponse也会被调用。你可以从response.errorBody().string()中获取错误信息的主体。
缺少INTERNET权限会导致SecurityException异常
在Retrofit 1.9中,如果你忘记在AndroidManifest.xml文件中添加INTERNET权限。异步请求会直接进入failure回调方法,得到PERMISSION DENIED 错误消息。没有任何异常被抛出。
但是在Retrofit 2.0中,当你调用call.enqueue或者call.execute,将立即抛出SecurityException,如果你不使用try-catch会导致崩溃。
Use an Interceptor from OkHttp
在Retrofit 1.9中,你可以使用RequestInterceptor来拦截一个请求,但是它已经从Retrofit 2.0 移除了,因为HTTP连接层已经转为OkHttp。
结果就是,现在我们必须转而使用OkHttp里面的Interceptor。首先你需要使用Interceptor创建一个OkHttpClient对象,通常的应用时用于拦截OkHttp日志
HttpLoggingInterceptor interceptor =new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
client =new OkHttpClient.Builder()
.addInterceptor(interceptor)
.retryOnConnectionFailure(true)
.connectTimeout(15, TimeUnit.SECONDS)
.addNetworkInterceptor(authorizationInterceptor)
.build();
然后传递创建的client到Retrofit的Builder链中。
Retrofit retrofit=new Retrofit.Builder()
.baseUrl("http://api.nuuneoi.com/base/")
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
RxJava Integration with CallAdapter
RxJava准备的CallAdapter,它将作为Observable返回。要使用它,你的项目依赖中必须包含两个modules。
compile 'io.reactivex:rxandroid:1.2.1'
compile 'com.squareup.retrofit:adapter-rxjava:2.1.0'
Gradle并在Retrofit Builder链表中如下调用addCallAdapterFactory:
Retrofit retrofit=new Retrofit.Builder()
.baseUrl("http://api.nuuneoi.com/base/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
Observable observable=service.loadDessertListRx();
网友评论