Retrofit封装和使用

关于Retrofit基础知识的学习,请参考这篇文章

Retrofit实战技巧

代码的封装

1.APIService 使用Retrofit要求我们将项目中使用的接口请求定义写在一个接口中,咱们就写在APIService中。

2.RetrofitClient类,该类就是retrofit请求管理类,该类使用单例模式,封装了项目使用的Intercepter、baseUrl、connectTimeOut、convertFactory等,

 private RetrofitClient() {
    OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
    if (ColorVConst.DEBUG) {
        HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
        logging.setLevel(HttpLoggingInterceptor.Level.BASIC);
        okHttpClientBuilder.addInterceptor(logging);
    }
    okHttpClientBuilder.addInterceptor(new HeaderInterceptor())
            .addInterceptor(new ResponseIntercepter())
            .connectTimeout(DEFAULT_TIME_LIMIT, TimeUnit.SECONDS)
            .build();

    Retrofit retrofit = new Retrofit.Builder()
            .client(okHttpClientBuilder.build())
            .baseUrl(ServerInterfaceConst.BACK_SERVER)
            .addConverterFactory(JsonConverterFactory.create())
            .build();
    apiService = retrofit.create(APIService.class);
}

public APIService getApiService() {
   //通过该方法就能得到1中的ApIService对象
    return apiService;
}

3.HeadIntercepter类,因为咱们每次请求都需要向服务器发送utk,所以统一发送Header比较方便,所以就在retrofit请求的时候进行拦截,将header加到请求中,自定义Intercepter需要实现Intercepter接口,并实现intercept方法。

public class HeaderInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
    Request.Builder builder = chain.request()
            .newBuilder();
    try {
        Map<String, String> headers = ServerHandler.getCommonHeaders();
        for (String key : headers.keySet()) {
            builder.addHeader(key, headers.get(key));
        }
    } catch (JSONException e) {
        e.printStackTrace();
    }
    return chain.proceed(builder.build());
}

}

4.ResponseIntercepter 因为咱们部分json返回的时候Content-Encoding格式为gzip,而retrofit好像没处理这种情况,所以需要对返回后的数据进行拦截并处理。

5.JsonConverterFactory 该类描述了在请求数据时和返回数据时序列化反序列化的规则,该类继承Converter.Factory,并需要实现两个方法

public class JsonConverterFactory extends Converter.Factory {
public static JsonConverterFactory create() {
    return new JsonConverterFactory(new Gson());
}

private Gson gson;

private JsonConverterFactory(Gson gson) {
    if (gson == null) throw new NullPointerException("gson == null");
    this.gson = gson;
}

@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
    //表示返回的数据反序列化为Java Bean的规则
    return new JsonResponseBodyConverter<>(type, gson, annotations);
}

@Override
public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
    TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
    //表示请求的数据对象序列化为json的规则
    return new JsonRequestBodyConverter<>(gson, adapter);
}

}

5.JsonRequestBodyConverter 表示post请求的数据对象序列化为json的规则 里面实现使用gson序列化,如果实体类规范,可以直接使用实体类,如果不规范,还是直接使用JSONObject比较好。(待测试)

6.JsonResponseBodyConverter 在这里面处理返回结果的解析,因为实体类的不规范,gson解析不行,所以需自行处理,在我们需要实体类被解析的时候,实体类必须实现ParseInterface接口并实现T parse(JSONObject jsonObject)方法,因为JsonResponseBodyConverter里面处理解析就是根据该接口的解析方法进行解析的,如果不实现该接口或者该接口的解析方法体为空,那实体类将不能被完整解析,另外需要注意的是,该解析只支持解析为T或List,不支持解析成Map什么的。

7.ParseInterface 该类就是被解析的实体类需要实现的接口

Retrofit工具类的使用

1.在APIService中声明接口和参数

 /*
    @Query @QueryMap : 用于Http Get请求传递参数

    @Field : 用于Post方式传递参数,需要在接口方法上添加@FormUrlEncoded,即以表单的方式传递参数

    @Body : 用于Post,根据转换方式将实例对象转化为对应字符串传递参数,比如Retrofit添加GsonConverterFactory则是将body转化为gson字符串进行传递

    @Path : 用于URL上占位符{}

    @Part : 配合@Multipart使用,一般用于文件上传

    @Header : 添加HttpHeader

    @Headers : 跟@Header作用一样,只是使用方式不一样,@Header是作为请求方法的参数传入,@Headers是以固定方式直接添加到请求方法上
 */
String USER_INFO = "user/{user_id}/info";
String USER_LIST = "user/{id}/{type}";

@GET(USER_INFO)
Call<User> userDetail(@Path("user_id") Integer userId, @QueryMap Map<String, String> map);

@GET(USER_LIST)
Call<List<User>> userList(@Path("id") Integer userId, @Path("type") String type, @Query("seq") String seq, @Query("length") Integer length, @Query("post_id") Integer postId);

2.将要被解析的实体类实现ParseInterface接口,并实现解析接口,例如:

@Override
public User parse(JSONObject jsonObject) {
    try {
        return ServerHandler.getUser(jsonObject, null, null, null);
    } catch (JSONException e) {
        e.printStackTrace();
    }
    return null;
}

3.进行网络请求

Map<String, String> map = new HashMap<>();
        map.put("kind", "summary");
        Call<User> userCall = RetrofitClient.getInstance().getApiService().userDetail(ServerInterfaceHandler.getCurrentUserId(), map);
        userCall.enqueue(new Callback<User>() {
            @Override
            public void onResponse(Call<User> call, Response<User> response) {
                LogUtils.d("thread_onResponse", Thread.currentThread().getName() + "-" + Thread.currentThread().getId());
                User user = response.body();
                //需要判断是否为空,因为不能正常解析的时候(只要不出异常也会回调onResponse,出异常则回调onFailure)这里会出现空指针的情况
                if(user != null) {
                    textView.setText(user.getName());
                }
            }

            @Override
            public void onFailure(Call<User> call, Throwable t) {
                ToastUtils.toastAbove(TestActivity.this, "请求失败");
            }
        });

4.可以对请求进行取消,调用userCall.cancel()方法,比如在界面销毁的时候就可以取消当前正在请求的接口。

5.对同一个接口再次请求userCall.clone().enqueue(…);

猜你喜欢

转载自blog.csdn.net/qq_33666539/article/details/56676055