Retrofit框架替换AsyncHttpClient框架

1.背景

1)项目中原来使用了 AsyncHttpClient框架。这套框架不满足 https + sni 的需要,需要改造。

2)具体的页面中,有约100个接口,在200+ 处使用了AsyncHttpClient,格式类似于

	RequestParams params = new RequestParams();
	params.put("userId", hostUserId);
	params.put(...);
	new AsyncHttpClient().getUserList(params, new TextHttpResponseHandler(){
		@override
		public abstract void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable){
			// 具体实现
		}
		@override
		public abstract void onSuccess(int statusCode, Header[] headers, String responseString){
			// 具体实现
		}
	});


3)接口返回的数据格式不尽相同

4)每个接口的完整url(除接口参数外),包括方法名,都可以通过url管理类获取,类似于

String url_get_user_list = UrlHelper.get_user_list        =>       http://xxx.yyy.com/api?aaa/bbb?cc=12&dd=dsd&method=app.user.list


2.目标

1)引入retrofit 支持https+sni

2)构建合适的框架,以简单快速的替换200+ 处的 AsyncHttpClient 的使用


具体实现

1.定义一个类似于TextHttpResponseHandler的回调接口,剥离回调接口与具体网络框架的耦连

public abstract class TextCallback {
    public abstract void onFailure(int statusCode, okhttp3.internal.http2.Header[] headers, String responseString, Throwable throwable);
    public abstract void onSuccess(int statusCode, okhttp3.internal.http2.Header[] headers, String responseString);
}

这里的Header属于什么类无所谓,因为页面的逻辑处理中并没有用到header


2.定义一个中间管理类和公共方法,连接具体页面与实际的网络框架,使页面与网络框架解耦,类似于

public class NetManager {      
    public static void go(Object tag, int methodType, String url, Map<String, Object> params, int time, TextCallback callback){

// 这里访问实际的网络框架类
        RetrofitHelper.enqueue(tag, methodType, url, params, callback);
    }
}

这个公共方法只接收如下参数

tag 用于在页面销毁时取消tag对应的网络请求

methodType 方法类型,如get  post等等

url 完整的url,包含了方法名

params 接口方法规定的参数

TextCallback 回调对象

3.定义retrofitservice

这里的需求是简单快速的替换约100个接口,所以不能像如下一样,给每个接口定义一种方法,这样太麻烦

@GET()
Call<List<User>> getUserList(@Query("userId") String hostUserId, @Query("pageNumber") int pageNumber, @Query("pageNumber") int pageNumber);

@GET()
Call<UserProfile> getUserProfile(@Query("userId") String userId);


所以,写成如下格式

@GET()
    Call<ResponseBody> getWithMap(@Url String url, @QueryMap Map<String, Object> param);


    @FormUrlEncoded
    @POST()
    Call<ResponseBody> postWithMap(@Url String url, @FieldMap Map<String, Object> param);

为什么回调类型写成ResponseBody:因为在retrofit中使用GsonConverterFactory时,这转换工厂会把如下格式的数据

{"userId":"ssde4", "userPhone":null,...}

转换为

{"userId":"ssde4",...}

自动去掉为null的字段的key。而页面在解析时获取userPhone,是这么写的

String s = {"userId":"ssde4",...}

new JsonObject(s).getString("userPhone")

会导致 JSONObject exception: No value for userPhone。这种写法在项目已有的代码中出现多处,为了避免一一修改,因此没有在retrofit的okhttpclient中使用任何converterFactory,直接回调ResponseBody


4.定义实际使用的retrofit工具类,类似于


public class RetrofitHelper {
    public static final int METHOD_GET = 1;
    public static final int METHOD_POST = 2;
    public static void enqueue(Object tag, int methodType,String fullUrl, Map<String, Object> param, final TextCallback callback){
        OkHttpClient.Builder okClientBuilder = new OkHttpClient
                .Builder()                
		.addInterceptor(new MyLogInterceptor());

        List<Interceptor> interceptors = new ArrayList<>();
        if(XXX){
            interceptors.add(new XXXInterceptor());
        }
        for (Interceptor interceptor : interceptors){
            okClientBuilder.addInterceptor(interceptor);
        }

        RetrofitService retrofitService = new Retrofit.Builder()
                .client(okClientBuilder.build())
                .baseUrl("因为使用了@url,所以这里的baseurl随便写")
                .build()
                .create(RetrofitService.class);

        Call<ResponseBody> call = null;
        if(methodType == METHOD_GET){
            call = retrofitService.getWithMap(fullUrl, param);
        }else if(methodType == METHOD_POST){
            call = retrofitService.postWithMap(fullUrl, param);
        }
        if(call != null){
            CallContainer.attachTag(tag, call); // 保存tag与call的关联关系

            call.enqueue(new Callback<ResponseBody>() {
                @Override
                public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                    ResponseBody body = response.body();
                    if(body == null){
                        String msg = "";
                        try{
                            msg = response.errorBody().string();
                        }catch (IOException e){
                            LogUtil.debug("enqueue", "" + e.getMessage());
                        }
                        callback.onFailure(response.raw().code(), null, msg, new XXXException("AAA"));
                    }else {
                        try{
                            String rawString = body.string();
                            String newRes = preHandleResult(response.raw().request().url().toString(), rawString);
                            callback.onSuccess(response.raw().code(), null, newRes);
                        } catch (IOException e) {
                            e.printStackTrace();
                            callback.onFailure(XXX, null, "", e);
                        }

                    }
                }

                @Override
                public void onFailure(Call<ResponseBody> call, Throwable t) {
                    LogUtil.debug("onFailure", "" + t.getMessage());
                    callback.onFailure(YYY, null, "", t);
                }
            });
        }


    }

        

   




























猜你喜欢

转载自blog.csdn.net/ronaldo4511/article/details/72782289