Retrofit+OKHttp+MVP的Android架构已经火了很久了,我自己也使用了有一段时间,但由于一直忙于这样或那样的事,一直没有做相关的笔记。年底先来无事,又重新看一了一遍相关的资料,做点笔记(好记性不如烂笔头)。
使用的相关库:
//网络请求依赖
compile 'com.squareup.okio:okio:1.13.0'
compile 'com.squareup.okhttp3:okhttp:3.8.1'
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-scalars:2.3.0'
第一步:先使用Retrofit最基本的用法
1.创建对应的API接口
public interface ApiService {
@GET
Call<String> get(@Url String url, @QueryMap WeakHashMap<String, Object> params);
}
使用WeakHashMap的原因是该容器使用的是弱引用有利于gc回收。
2.在需要访问的Activity类中添加访问请求代码:
private void netTest1(){
//Retorfit对象
Retrofit retrofit=new Retrofit.Builder()
.client(new OkHttpClient())
.baseUrl("https://www.baidu.com/")
.addConverterFactory(ScalarsConverterFactory.create())
.build();
//接口
ApiService apiService=retrofit.create(ApiService.class);
Call<String> call=apiService.get("",new WeakHashMap<String, Object>());
//发起网络请求
call.enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, Response<String> response) {
if (response.isSuccessful()){
Toast.makeText(getApplicationContext(),response.body(),Toast.LENGTH_LONG).show();
}
}
@Override
public void onFailure(Call<String> call, Throwable t) {
}
});
}
Retrofit创建对象的时候需要添加
Http通信类:OkHttp
基本网络地址:baseUrl(如果一个项目有多个不一样的主Host会很蛋疼),并且要反斜杠结束
ResponseBody返回类型:ScalarsConverterFactory(字符串)
3.调用:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
netTest1();
}
结果如下:
可以看到访问百度地址请求已经成功了!
很显然,每次调用网络的时候我们都需要重复写这段代码。
那就的做法是写个Utils吧(一般做法)。
第二步:抽出一个Utils调用
1.编写utils工具类
public class RetorfitUtils {
public static void request(String url, WeakHashMap<String,Object> params,Callback callback){
//Retorfit对象
Retrofit retrofit=new Retrofit.Builder()
.client(new OkHttpClient())
.baseUrl("https://www.baidu.com/")
.addConverterFactory(ScalarsConverterFactory.create())
.build();
//接口
ApiService apiService=retrofit.create(ApiService.class);
Call<String> call=apiService.get(url,new WeakHashMap<String, Object>());
//发起网络请求
call.enqueue(callback);
}
}
2.Activity调用
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WeakHashMap<String,Object> params=new WeakHashMap<>();
RetorfitUtils.request("", params, new Callback<String>() {
@Override
public void onResponse(Call<String> call, Response<String> response) {
if (response.isSuccessful()){
Toast.makeText(getApplicationContext(),response.body(),Toast.LENGTH_LONG).show();
}
}
@Override
public void onFailure(Call call, Throwable t) {
}
});
}
结果:
可以看到结果与上面一致。
仔细想想,这个Utils工具类只是将我们经常调用请求代码抽出来,方便使用但代码的运行效率并没有得到优化。发起多个网络请求还是会多次实例化Retorfit/ApiService,所以工具中得将Retorfit/ApiService单利化了。最重要这种utils太没逼格了。
第三步:将Retorif进行二次封装
根据Retrofit的基本使用,主要封装思路:
ApiService对象(单利)
Retrofit对象(单利)
Http请求OkHttpClient对象(单利)
请求参数/接口回调(建造者模式)
1.创建基本Api接口BaseApiService
public interface BaseApiService {
@GET
Call<String> get(@Url String url, @QueryMap WeakHashMap<String, Object> params);
@FormUrlEncoded
@POST
Call<String> post(@Url String url, @FieldMap WeakHashMap<String, Object> params);
@FormUrlEncoded
@PUT
Call<String> put(@Url String url, @FieldMap WeakHashMap<String, Object> params);
@DELETE
Call<String> delete(@Url String url, @QueryMap WeakHashMap<String, Object> params);
}
2.定义好相关回调接口(访问开始/访问成功/逻辑错误/访问失败/访问结/Callbak)
访问开始
public interface IRequestStart {
void onRequestStart();
}
访问成功
public interface ISuccess {
void onSuccess(String response);
}
逻辑错误
public interface IError {
void onError(int code,String msg);
}
访问失败
public interface IFailure {
void onFailure();
}
访问结束
public interface IRequestEnd {
void onRequestEnd();
}
Callbak
public class RequestCallBacks implements Callback<String>{
private final ISuccess SUCCESS;
private final IError ERROR;
private final IFailure FAILURE;
private final IRequestEnd REQUEST_END;
public RequestCallBacks(ISuccess success, IError error, IFailure failure, IRequestEnd requestEnd) {
this.SUCCESS = success;
this.ERROR = error;
this.FAILURE = failure;
this.REQUEST_END = requestEnd;
}
@Override
public void onResponse(Call<String> call, Response<String> response) {
if (response.isSuccessful()){
if (call.isExecuted()){
if (SUCCESS!=null){
SUCCESS.onSuccess(response.body());
}
}
}else{
if (ERROR!=null){
ERROR.onError(response.code(),response.message());
}
}
if (REQUEST_END!=null){
REQUEST_END.onRequestEnd();
}
}
@Override
public void onFailure(Call<String> call, Throwable t) {
if (FAILURE!=null){
FAILURE.onFailure();
}
}
}
为了确保传进来的参数不被修改,所以定义为final
3.创建一个专门生成Retrofit/ApiService的类ClientCreator
public class ClientCreator {
/**创建Retorfit*/
private static final class RetrofitHolder{
private static final String BASE_URL="https://www.baidu.com/";
private static final Retrofit RETROFIT=new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(OkHttpClienHolder.OK_HTTP_CLIENT)
.addConverterFactory(ScalarsConverterFactory.create())
.build();
}
/**创建OkHttpClien对象*/
private static final class OkHttpClienHolder{
private static final int TIME_OUT=120;
private static final OkHttpClient OK_HTTP_CLIENT=new OkHttpClient.Builder()
.connectTimeout(TIME_OUT, TimeUnit.SECONDS)
.build();
}
/**构建ApiService对象*/
private static final class ApiServiceHolder{
private static final BaseApiService API_SERVICE=RetrofitHolder.RETROFIT.create(BaseApiService.class);
}
/**获取BaseApiService对象*/
public static BaseApiService getBaseApiService(){
return ApiServiceHolder.API_SERVICE;
}
}
4.定义请求方式HttpMethod
public enum HttpMethod {
GET,
POST,
PUT,
DELETE
}
5.根据构建者模式创建出暴露出来给我们调用的类MyHttpClient/HttpClientBuilder
MyHttpClient中的参数是通过HttpClientBuilder来进行设置
MyHttpClient
public class MyHttpClient {
private final String URL;
private final WeakHashMap<String,Object> PARAMS;
private final IRequestStart REQUEST_START;
private final ISuccess SUCCESS;
private final IError ERROR;
private final IFailure FAILURE;
private final IRequestEnd REQUEST_END;
MyHttpClient(String url, WeakHashMap<String,Object> params,IRequestStart requestStart, ISuccess success, IError error, IFailure failure, IRequestEnd requestEnd) {
this.URL = url;
PARAMS=params;
this.REQUEST_START = requestStart;
this.SUCCESS = success;
this.ERROR = error;
this.FAILURE = failure;
this.REQUEST_END = requestEnd;
}
public static HttpClientBuilder builder(){
return new HttpClientBuilder();
}
private RequestCallBacks getRequestCallBacks(){
return new RequestCallBacks(
SUCCESS,
ERROR,
FAILURE,
REQUEST_END
);
}
private void requset(HttpMethod method){
Call<String> call=null;
BaseApiService apiService=ClientCreator.getBaseApiService();
if (REQUEST_START!=null){
REQUEST_START.onRequestStart();
}
switch (method){
case GET:
call=apiService.get(URL,PARAMS);
break;
case POST:
call=apiService.post(URL,PARAMS);
break;
case PUT:
call=apiService.put(URL,PARAMS);
break;
case DELETE:
call=apiService.delete(URL,PARAMS);
break;
default:
break;
}
if (call!=null){
call.enqueue(getRequestCallBacks());
}
}
public void get(){
requset(HttpMethod.GET);
}
public void post(){
requset(HttpMethod.POST);
}
public void put(){
requset(HttpMethod.PUT);
}
public void delete(){
requset(HttpMethod.DELETE);
}
}
HttpClientBuilder
public class HttpClientBuilder {
private String mUrl;
private final WeakHashMap<String,Object> PARAMS=new WeakHashMap<>();
private IRequestStart mRequestStart;
private ISuccess mSuccess;
private IError mError;
private IFailure mFailure;
private IRequestEnd mRequestEnd;
/**
* 设置接口路径
* @param url:接口路径
* */
public final HttpClientBuilder url(String url){
this.mUrl=url;
return this;
}
/**
* 设置请求参数
* @param key:
* @param val:
* */
public final HttpClientBuilder params(String key,Object val){
this.PARAMS.put(key,val);
return this;
}
/**
* 设置请求参数
* @param params:请求参数
* */
public final HttpClientBuilder params(WeakHashMap<String,Object> params){
this.PARAMS.putAll(params);
return this;
}
/**
* 设置访问开始接口回调
* @param requestStart:
* */
public final HttpClientBuilder questStart(IRequestStart requestStart){
this.mRequestStart=requestStart;
return this;
}
/**
* 设置访问成功接口回调
* @param success:
* */
public final HttpClientBuilder success(ISuccess success){
this.mSuccess=success;
return this;
}
/**
* 设置访问错误接口回调
* @param error:
* */
public final HttpClientBuilder error(IError error){
this.mError=error;
return this;
}
/**
* 设置访问失败接口回调
* @param failure:
* */
public final HttpClientBuilder failure(IFailure failure){
this.mFailure=failure;
return this;
}
/**
* 设置访问结束接口回调
* @param requestEnd:
* */
public final HttpClientBuilder requestEnd(IRequestEnd requestEnd){
this.mRequestEnd=requestEnd;
return this;
}
/**创建MyHttpClient*/
public MyHttpClient build(){
return new MyHttpClient(
mUrl,
PARAMS,
mRequestStart,
mSuccess,
mError,
mFailure,
mRequestEnd
);
}
}
6.Activity调用
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyHttpClient.builder()
.url("")
.params("name","张三")
.questStart(new IRequestStart() {
@Override
public void onRequestStart() {
//loading start
}
})
.success(new ISuccess() {
@Override
public void onSuccess(String response) {
Toast.makeText(getApplicationContext(),response,Toast.LENGTH_LONG).show();
}
})
.error(new IError() {
@Override
public void onError(int code, String msg) {
}
})
.failure(new IFailure() {
@Override
public void onFailure() {
}
})
.requestEnd(new IRequestEnd() {
@Override
public void onRequestEnd() {
// loading hide
}
})
.build()
.get();
}
运行结果:
与上面结果一致。
从调用的结构可以看出这种建造者模式使用起来就像一条链一样,从请求url,参数,接口回调,需要设置哪个就建造对应的数据,使用起来清晰方便。当然,项目开发中,我们往往不会直接返回字符串,所以还可以封装一个泛型,让成功回调返回泛型。
后续….