如未接触过Retrofit,请先看以下内容:
1.Android网络请求框架之Retrofit(一)
2.Android网络请求框架之Retrofit(二)
第一篇文章我们讲述了Retrofit的基本用法,让大家对Retrofit有了一定的认识,第二篇文章讲述了Rx模式和Retrofit结合的用法,让大家接触Rx模式和进一步了解Retrofit。下面我将为大家讲述Retrofit1.9.0版本和2.0.0版本API的差异。
同步请求
Retrofit1
public interface TaskService {
@GET("/tasks")
List<Task> getTasks();
}
Retrofit2
public interface TaskService {
@GET("/tasks")
Call<List<Task>> getTasks();
}
可以很清楚的看出他们的区别:1.9.0版本,数据直接通过方法的返回值获取,2.0.0版本则是把数据包装到Call对象里。同步方法实在主线程执行的,所以在Android4.0及以上版本会抛出NetworkOnMainThreadException异常,所以在调用的时候要自己放到子线程里去执行,然后通过Handler更新界面。
同步方法里获取数据
Retrofit1
TaskService taskService = ServiceGenerator.createService(TaskService.class);
List<Task> tasks = taskService.getTasks();
Retrofit2
TaskService taskService = ServiceGenerator.createService(TaskService.class);
Call<List<Task>> call = taskService.getTasks();
List<Task>> tasks = call.execute().body();
异步请求
Retrofit1
public interface TaskService {
@GET("/tasks")
void getTasks(Callback<List<Task>> cb);
}
Retrofit2
public interface TaskService {
@GET("/tasks")
Call<List<Task>> getTasks();
}
可以看到,同步和异步请求在2.0.0版本是一样的,1.9.0才有所区别,但是这针对的是请求,数据获取还是有所区别的。
异步方法里获取数据
Retrofit1
TaskService taskService = ServiceGenerator.createService(TaskService.class);
taskService.getTasks(new Callback<List<Task>>() {
@Override
public void success(List<Task> tasks, Response response) {
// here you do stuff with returned tasks
}
@Override
public void failure(RetrofitError error) {
// you should handle errors, too
}
});
Retrofit2
TaskService taskService = ServiceGenerator.createService(TaskService.class);
Call<List<Task>> call = taskService.getTasks();
call.enqueue(new Callback<List<Task>>() {
@Override
public void onResponse(Call<List<Task>> call, Response<List<Task>> response) {
if (response.isSuccess()) {
// tasks available
} else {
// error response, no access to resource?
}
}
@Override
public void onFailure(Call<List<Task>> call, Throwable t) {
// something went completely south (like no internet connection)
Log.d("Error", t.getMessage());
}
}
对于异步方法来说,我们最后都必须传入一个Callback接口,实现它的success方法和onFailure方法,不同的是,1.9.0的Callback作为一个参数传递到方法里,2.0.0先返回一个Call对象,再调用Call对象的enqueue方法,传入Callback对象去获取数据。
请求载体的区别
Retrofit1
public synchronized RestAdapter build(final String url) {
//这就是发起请求的对象
RestAdapter adapter = null==adapters.get(url)?null:adapters.get(url).get();
if (null == adapter) {
final CellInfo cellInfo = Utils.getCellInfo();
//添加一些header
RequestInterceptor requestInterceptor = new RequestInterceptor() {
@Override
public void intercept(RequestFacade request) {
request.addHeader("Authorization", String.format("Bearer %s", MainApp.getToken()));
request.addHeader("LoyoPlatform", cellInfo.getLoyoPlatform());
request.addHeader("LoyoAgent", cellInfo.getLoyoAgent());
request.addHeader("LoyoOSVersion", cellInfo.getLoyoOSVersion());
request.addHeader("LoyoVersionName", Global.getVersionName());
request.addHeader("LoyoVersionCode", String.valueOf(Global.getVersion()));
}
};
//指定url,设置log级别,设置拦截器。。。。。。
adapter = new RestAdapter.Builder().setEndpoint(url).setLogLevel(RestAdapter.LogLevel.FULL).setRequestInterceptor(requestInterceptor).build();
adapters.put(url, new SoftReference<>(adapter));
}
return adapter;
}
Retrofit2
public synchronized <S> S create(Class<S> serviceClass, final String token) {
httpClient.interceptors().clear();
if (token != null) {
httpClient.interceptors().add(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
Request.Builder requestBuilder = original.newBuilder()
// .header("Accept", "applicaton/json")
.header("AccessToken", token);
// .method(original.method(), original.body());
Request request = requestBuilder.build();
return chain.proceed(request);
}
});
}
//请求发起者
Retrofit retrofit = builder.client(httpClient).build();
return retrofit.create(serviceClass);
}
1.9.0的请求发起者是RestAdapter,2.0.0的直接就叫Retrofit。并且在设置header和log级别上也有所差异。1.9.0可以再builder里直接指定log级别,2.0.0需要引入compile 'com.squareup.okhttp:logging-interceptor:2.6.0'
这个库来设置log级别,当然,也可以自己实现Interceptor来自定义日志输出
class LoggingInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
long t1 = System.nanoTime();
String requestLog = String.format("Sending request %s on %s%n%s",
request.url(), chain.connection(), request.headers());
//YLog.d(String.format("Sending request %s on %s%n%s",
// request.url(), chain.connection(), request.headers()));
if (request.method().compareToIgnoreCase("post") == 0) {
requestLog = "\n" + requestLog + "\n" + bodyToString(request);
}
Log.d("TAG", "request" + "\n" + requestLog);
Response response = chain.proceed(request);
long t2 = System.nanoTime();
String responseLog = String.format("Received response for %s in %.1fms%n%s",
response.request().url(), (t2 - t1) / 1e6d, response.headers());
String bodyString = response.body().string();
Log.d("TAG", "response" + "\n" + responseLog + "\n" + bodyString);
return response.newBuilder()
.body(ResponseBody.create(response.body().contentType(), bodyString))
.build();
}
private String bodyToString(final Request request) {
try {
final Request copy = request.newBuilder().build();
final Buffer buffer = new Buffer();
copy.body().writeTo(buffer);
return buffer.readUtf8();
} catch (final IOException e) {
return "did not work";
}
}
}
当然,Retrofit1.9.0和2.0.0的区别远远不止这些,比如2.0.0版本引入的库比1.9.0要多很多,但是他们最直观的区别应该就是2.0.0完全采用函数式编程思想来实现,即使代码数量过多,也可以很好地控制代码结构和理清代码逻辑,从这点来说,2.0.0还是我比较喜欢的。期待大家去发掘更多的新奇用法。