好几个月没有搞android的东西,感觉自己拉下很多,正好最近有个新项目,就顺便研究一下现在很火的Retrofit和Rxjava。
这个专题我打算写三篇,分别介绍Retrofit,Rxjava以及如何将两者结合起来。
本篇先介绍比较简单的Retrofit
一. 为什么要使用Retrofit
因为简洁,好用,而且效率高(关于效率这一点,我曾经看到过一个请求耗时的对比,但是对不起各位看官,我搜了好多地方都没有找到这个数据)。
我先写一个”远古时期”我们经常用到的网络请求以及处理流程。
通常我们在网络请求后会再处理UI线程,所以我们往往一个组合是HTTPClient+AsyncTask
一个简单的Client的get请求
// 使用线程安全的连接管理来创建HttpClient
ClientConnectionManager conMgr = new ThreadSafeClientConnManager(params, schReg);
DefaultHttpClient client = new DefaultHttpClient(conMgr, params);
HttpGet request = new HttpGet(URL);
HttpResponse response = client.execute(request);
int httpStatusCode = response.getStatusLine().getStatusCode();
if (httpStatusCode == HttpStatus.SC_OK) {
result = EntityUtils.toString(response.getEntity());
} else {
throw new HttpException("Error Response:" + response.getStatusLine().toString());
}
return result;
最终我们得到了一个result,这里面是我们期望返回的数据(比如是一个json)。
为了让这个json数据为我所用,我们还需要把它转化成一个数据结构,这一步我们通常会使用Gson(相关代码省去不表)。
当然,上面的这个流程,你可以封装到一个类里面,无需每次都写这么多代码。
假设封装后,我们可以通过下面这个方法来调起这个网络请求并结构化数据
UserBean bean = new UserCenter(mContext).getUserInfo(token);
下面我们需要写一个AsyncTask,在它里面发起网络请求并处理数据,一个简单的AsyncTask通常是如下
private class GetUserInfoTask extends AsyncTask<Integer, Integer, UserBean> {
@Override
protected Result<UserBean> doInBackground(Integer... params) {
UserBean bean = new UserBean();
bean = new UserCenter(mContext).getUserInfo(token);;
return bean;
}
@Override
protected void onPostExecute(UserBean result) {
super.onPostExecute(result);
//TODO 处理返回的数据,显示在UI中
}
}
最后,你可以愉快(或者很不耐烦)地调用它了:
new GetUserInfoTask().execute();
而以上的这些,如果用retrofit,我们写出来是这样的(你不需要马上理解这些代码,后面我们会详细讲到):
public interface UserAPIService {
@GET("user")
Call<UserBean> getUserInfo(@Query("token") String token);
}
Retrofit appRetrofit = new Retrofit.Builder().baseUrl(url)
.addConverterFactory(GsonConverterFactory.create()).build();
Call<UserBean> call = appRetrofit.create(UserAPIService.class).getUserInfo(token);
call.enqueue(new Callback<UserBean>() {
@Override
public void onResponse(Response<UserBean> response) {
//TODO 处理返回的数据,显示在UI中
}
@Override
public void onFailure(Throwable t) {
//获取失败的逻辑
}
});
没了,这就是所有的代码,而且你还可以把其中很多代码封装起来,得到一个更简洁的版本。
我觉得这已经有足够的理由让我们去用retrofit了(反正我是学会后完全不想用asynctask什么的了)
二. 如何使用Retrofit
关于Retrofit原理和使用的文章网上非常多,如果大家想看更多详细的信息,可以去Github看Retrofit的源码(https://github.com/square/retrofit)
或者去看官方的使用说明(http://square.github.io/retrofit/)
我在下面不会非常详细的讲解Retrofit的原理和API,我只是想通过最少的文字,来教会大家如何使用它。
在开始之前,需要声明一点:网上有很多retrofit的使用说明,但是大都是1.x版本的,跟2.0版本有很大的区别(此篇博客发布时,最新的retrofit版本是2.0.0,我用的也是这个版本)
关于2.0的文章,非常推荐大家去看下面这一篇:
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0915/3460.html
首先,要使用Retrofit,我们需要创建一个Retrofit的实例,类似你要创建一个http client的实例是一样的:
Retrofit appRetrofit = new Retrofit.Builder().baseUrl(url)
.addConverterFactory(GsonConverterFactory.create()).build();
其中,baseUrl(url)就是设置我要请求的地址,比如我们的接口都是走的这个域名www.baidu.com/xxx,那这里你就应该url=www.baidu.com
addConverterFactory是一个很神奇的方法,它添加了一个数据的转化器,你可以把response返回的数据设置成很多格式,上面的代码里,我设置返回的数据自动转化成gson,除此之外,你还可以设置:
Gson: com.squareup.retrofit:converter-gson
Jackson: com.squareup.retrofit:converter-jackson
Moshi: com.squareup.retrofit:converter-moshi
Protobuf: com.squareup.retrofit:converter-protobuf
Wire: com.squareup.retrofit:converter-wire
Simple XML: com.squareup.retrofit:converter-simplexml
有上面两个方法后,我们还需要声明一个接口,用来存放各种请求和对应的参数:
public interface UserAPIService {
@GET("user")
Call<UserBean> getUserInfo(@Query("token") String token);
}
比如,你现在的接口是www.baidu.com/user?token=xxx,这是一个get请求,那么首先你应该用@GET(“user”)来表明我们要发起的是一个get请求,它的地址是user(www.baidu.com我们已经用baseUrl方法定义过了)
然后我们要定义一个方法用来请求数据,这个方法名随意,这里我们叫getUserInfo
注意这个方法的返回值是固定格式的,它一定是Call<T>
, 因为我们之前设置过用gson来解析数据,所以这里T不能是一个基本类型或者String之类的,它应该是一个bean。
然后看它的参数@Query(“token”) String token,这里get最基础的参数,类似www.baidu.com/user?token=xxx这种的我们可以用@Query来表示,除此之外,它还支持:
@Path:如果我们地址中某个路径是动态的,类似下面:
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId);
@QueryMap:一些复杂的参数,你可以通过map传进来
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options);
post请求可以用@Body
@POST("users/new")
Call<User> createUser(@Body User user);
这样,对应的接口,返回的数据结构,需要的参数,我们都定义好了。
剩下的就是调用了:
//创建一个UserAPIService的call,然后调用对应的请求
Call<UserBean> call = appRetrofit.create(UserAPIService.class).getUserInfo(token);
//enqueue用来设置一个回调Callback,你可以在Callback里面处理返回的数据,Callback运行在主线程
call.enqueue(new Callback<UserBean>() {
@Override
public void onResponse(Response<UserBean> response) {
//TODO 处理返回的数据,显示在UI中
}
@Override
public void onFailure(Throwable t) {
//获取失败的逻辑
}
});
上面的enqueue方法,我们也可以不写,而是在UserAPIService指定一个CallBack,这样的话,UserAPIService就是下面这样:
public interface UserAPIService {
@GET("user")
Call<UserBean> getUserInfo(@Query("token") String token, CallBack<UserBean> callBack);
}
那就不需要enqueue了,而是:
//创建一个UserAPIService的call,然后调用对应的请求
Call<UserBean> call = appRetrofit.create(UserAPIService.class).getUserInfo(token, new Callback<UserBean>() {
@Override
public void onResponse(Response<UserBean> response) {
//TODO 处理返回的数据,显示在UI中
}
@Override
public void onFailure(Throwable t) {
//获取失败的逻辑
}
});
看起来更简洁了。
以上就是Retrofit的使用教程,相信你很快也可以搭建出来一个基于Retrofit的工程