写在开头:retrofit +rxjava 称得上完美搭档。
特点
- 性能最好,处理最快
- 使用REST API时非常方便;
- 传输层默认就使用OkHttp;
- 支持NIO;
- 拥有出色的API文档和社区支持
- 速度上比volley更快;
- 如果你的应用程序中集成了OKHttp,Retrofit默认会使用OKHttp处理其他网络层请求。
- 默认使用Gson
使用
Retrofit支持同步和异步两种方式,在使用时,需要将请求地址转换为接口,通过注解来指定请求方法,请求参数,请求头,返回值等信息。还是使用之前的person的那段json值,get请求到服务器后从数据库查询数据,返回值为查询到的数据,post请求向服务器提交一条数据,返回值为提交的数据。
首先完成请求所用的service,是一个interface,完全通过注解完成配置
package cn.edu.zafu.http;
import retrofit.Callback;
import retrofit.http.Field;
import retrofit.http.FormUrlEncoded;
import retrofit.http.GET;
import retrofit.http.Headers;
import retrofit.http.POST;
import retrofit.http.Path;
import retrofit.http.Query;
/**
* Created by lizhangqu on 2015/5/11.
*/
public interface PersonService {
@Headers({
"Cache-Control: max-age=640000",
"User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"
})
//通过注解设置请求头
@GET("/{test}/rest.php")
//设置请求方法为get,相对路径为注解内内容,其中{test}会被@Path注解指定内容替换
Person getPerson(@Path("test") String dir,@Query("name") String name);
//@Query用于指定参数
@FormUrlEncoded
//urlencode
@POST("/test/rest1.php")
//post提交
Person updatePerson(@Field("name") String name,@Field("age") int age);
//@Field提交的域
@POST("/test/rest1.php")
void updatePerson(@Field("name") String name,@Field("age") int age, Callback<Person> callback);
//异步回调,不能指定返回值
}
- GET
使用时,通过RestAdapter的实例获得一个接口的实例,其本质是动态代理,注意含有返回值的方法是同步的,不能UI线程中调用,应该在子线程中完成
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("http://121.41.119.107")
.build();
PersonService personService=restAdapter.create(PersonService.class);
Person person=personService.getPerson("test","zhangsan");
Log.d("TAG",person.toString());
- POST
POST的调用同Get,获得adapter后获得一个代理对象,然后通过这个代理对象进行网络请求
Person person1=personService.updatePerson("lizhangqu", 12);
Log.d("TAG",person1.toString());
- 异步请求
如果要使用异步请求,需要将接口中的方法返回值修改会void,再加入回调参数Callback,就如PersonService中第三个方法一样,请求完成后会回调该callback对象的success或者fail方法。
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("http://121.41.119.107")
.build();
PersonService personService=restAdapter.create(PersonService.class);
personService.updatePerson("lizhangqu",23, new Callback<Person>() {
@Override
public void success(Person person, Response response) {
Log.d("TAG", person.toString());
}
@Override
public void failure(RetrofitError error) {
}
});
Retrofit的使用还有很多内容,剩下的就留给各位读者自行去发现了,而其官网页提供了及其详细的说明。下面提供官方网址
这个库里面有很多精华的内容,建议各位仔细的阅读下官方的文档。
--------------------------------------------------分割线--------------------------------------------------
使用Retrofit取消请求
场景:网络没有加载完关闭activity,如果不取消请求会内存泄露。
现在用的好多网络请求都用的异步回调,异步回调会导致这种问题发生,不过这种泄露基本都是短时的。
为了避免泄露,可以取消时有一个标志位, 取到数据之后, 若发现此标志位为true了, 就不再渲染页面。
发起了10个请求,但是他们到达的顺序可能不一样,那么此时渲染的数据是刚好那个点到达的数据,但是顺序无法保证,这时标志位不能很好解决问题。
--------------------------------------------------分割线--------------------------------------------------
注意:
java.lang.IllegalArgumentException: API interfaces must not extend other interfaces.
at retrofit2.Utils.validateServiceInterface(Utils.java:316)
at retrofit2.Retrofit.create(Retrofit.java:129)
源码:
static <T> void validateServiceInterface(Class<T> service) {
if (!service.isInterface()) {
throw new IllegalArgumentException("API declarations must be interfaces.");
}
// Prevent API interfaces from extending other interfaces. This not only avoids a bug in
// Android (http://b.android.com/58753) but it forces composition of API declarations which is
// the recommended pattern.
if (service.getInterfaces().length > 0) {
throw new IllegalArgumentException("API interfaces must not extend other interfaces.");
}
}
修改:
1.Retrofit favors composition over inheritance. One interface per service. 不能继承接口
2.java是不能实例化泛型的 DCApi<P92Bean> api = new DCApi<P92Bean>();错误
3.整个重新打包retrofit,修改Utils.validateServiceInterface