Retrofit 是什么
Retrofit 是一套 RESTful 架构的 Android(Java)客户端实现,基于注解,轻量级且安全的网络请求框架。
Retrofit具有如下优势:
- 使用 注解的方式简化了写客户端接口的方法,并且注解一目了然,简单易懂。
- 使用简单结构清晰,能清晰的表达出整个流程。
- 扩展性强,支持用户自定义业务逻辑和interceptor。
- 原生支持RxJava,可以很好的支持RxJava式的返回结果处理。
- 可以直接把服务端请求的数据转化为java对象,如json,xml数据直接转化为对象。
基本用法
Retrofit1.x版本的使用比较简单,首先定义一个拦截器,在拦截器里面设置请求参数等信息:
RequestInterceptor requestInterceptor = request -> {
request.addHeader("Accept", "text/html");
request.addHeader("os","Android");
request.addHeader("ver","1");
};
然后创建一个RestAdapter设置基础URL,拦截器,日志打印等:
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("http://baike.baidu.com/api/openapi")
.setRequestInterceptor(requestInterceptor)
.setLogLevel(RestAdapter.LogLevel.FULL)
// .setClient(new OkClient(new OkHttpClient()))
.build();
最后创建一个访问接口的API接口类:
public interface AbsApi {
@GET("BaikeLemmaCardApi")
Observable<jsonOut>
getBaidu(@Query("bk_key")String key);//获取信息
}
再创建一个接口实例就可以用过这个接口实例范文服务器接口了:
AbsApi mAbsApi = restAdapter.create(AbsApi.class);
相对于1.x版本,Retrofit2.0版本有几个不一样的地方:
- 必须指定OKHttp支持。
- 基础URL一定要以“/”结尾。
- 要手动指定数据格式支持,Retrofit1.x默认以Gson支持。
- 打印日志的interceptor必须手动添加。
在Retrofit2.0中,首先创建一个OKHttp客户端,添加日志支持,以及固定请求参数设置
//添加固定请求参数实例
Interceptor addQueryParameterInterceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
Request request;
String method = originalRequest.method();
Headers headers = originalRequest.headers();
HttpUrl modifiedUrl = originalRequest.url().newBuilder()
// Provide your custom parameter here
.addQueryParameter("scope", "103")
.addQueryParameter("format", "json")
.addQueryParameter("appid", "379020")
.addQueryParameter("bk_length", "600")
.build();
request = originalRequest.newBuilder().url(modifiedUrl).build();
return chain.proceed(request);
}
};
//打印日志
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
//新建OkHttp客户端
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.addInterceptor(addQueryParameterInterceptor)
.retryOnConnectionFailure(true)
.connectTimeout(15, TimeUnit.SECONDS)
.build();
然后用Retrofit类加载OKHttp客户端:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(FORUM_SERVER_URL)
.client(client)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
其他步骤与1.x一样。
Retrofit的常用注解
对于一般性的GET请求,注解如下:
@GET("BaikeLemmaCardApi")
Observable<jsonOut>
getBaidu(@Query("bk_key")String key);//获取新闻,直接将返回数据转化为JsonOut对象,bk_key为请求的参数
对于POST请求,有两种方法,第一种把请求的数据组装成一个对象直接用对象提交,第二种是用表单的方式一个一个数据单个提交:
@POST("user/register")
Observable<jsonOut>
register(@Body PostRegister register);//注册
@FormUrlEncoded
@POST("user/register")
Observable<jsonOut>
register(@Field("username") String username,@Field("password") String password,);//注册
对于上传图片的处理,把图片转化为TypedFile 类型,用@Multipart注解提交:
@Multipart
@POST("sys/upload")
Observable<jsonOut>
uploadFile(@Part("file") TypedFile file);//上传图片
对于REST接口:
@GET("news/{id}/getNews")
Observable<jsonOut>
getNews(@Path("id") String id);//获取新闻
封装Retrofit网络请求:
public class AbsService {
private static final String FORUM_SERVER_URL = "http://baike.baidu.com/api/openapi/";//基础URL
private AbsApi mAbsApi;
private volatile static AbsService singleton;
final static Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
.serializeNulls()
.create();
public AbsService() {
//公共参数
Interceptor addQueryParameterInterceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
Request request;
String method = originalRequest.method();
Headers headers = originalRequest.headers();
HttpUrl modifiedUrl = originalRequest.url().newBuilder()
// Provide your custom parameter here
.addQueryParameter("scope", "103")
.addQueryParameter("format", "json")
.addQueryParameter("appid", "379020")
.addQueryParameter("bk_length", "600")
.build();
request = originalRequest.newBuilder().url(modifiedUrl).build();
return chain.proceed(request);
}
};
//打印日志
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.addInterceptor(addQueryParameterInterceptor)
.retryOnConnectionFailure(true)
.connectTimeout(15, TimeUnit.SECONDS)
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(FORUM_SERVER_URL)
.client(client)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
mAbsApi = retrofit.create(AbsApi.class);
}
public AbsApi getApi() {
return mAbsApi;
}
//在这里定义,服务端的各种请求
public interface AbsApi {
@GET("BaikeLemmaCardApi")
Observable<jsonOut>
getBaidu(@Query("bk_key")String key);//获取新闻
}
public static AbsService getInstance() {//以单例模式访问AbsService
if (singleton == null) {
synchronized (AbsService.class) {
if (singleton == null) {
singleton = new AbsService();
}
}
}
return singleton;
}
public static AbsApi getService(){
return getInstance().mAbsApi;
}
}
在访问的时候,在Presenter层只要创建一个AbsService 实例,直接调用这个方法就可以了,异步返回的数据处理在onNext方法进行:
AbsService mAbsService=new AbsService();
mAbsService.getApi().getBaidu(key).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<jsonOut>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(jsonOut jsonOut) {
}
});
优化
对于服务器返回的数据,我们一般采用这种格式:
{
"code": 1,
"message": "success",
"data": {
}
}
因此,我们可以写一个模板:
public class AbsReturn<V> {
String message;
V data;
int code;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public V getData() {
return data;
}
public void setData(V data) {
this.data = data;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}
在写接口的时候就可以这样定义,以便于以后,对结果进行统一判断处理:
@GET("BaikeLemmaCardApi")
Observable<AbsReturn<jsonOut>>
getBaidu(@Query("bk_key")String key);