美文网首页Android开发
Retrofit网络请求,工具类的封装(二)。

Retrofit网络请求,工具类的封装(二)。

作者: 刘付文 | 来源:发表于2018-01-24 16:52 被阅读3552次

    对于Retrofit的使用我就不介绍了,使用也不难,随便去搜两篇文章看看。
    我主要介绍的就是如何封装,简便使用。
    数据的封装可以移步到:Retrofit网络请求,数据的封装(一)

    一、Retrofit工具类的封装(核心类)
     /**
     * Retrofit工具类
     */
    public class RetrofitUtils {
        public static final String BASE_URL = "http://XXX";
        /**
         * 超时时间
         */
        public static final int TIMEOUT = 60;
        private static volatile RetrofitUtils mInstance;
        private Retrofit mRetrofit;
    
        public static RetrofitUtils getInstance() {
            if (mInstance == null) {
                synchronized (RetrofitUtils.class) {
                    if (mInstance == null) {
                        mInstance = new RetrofitUtils();
                    }
                }
            }
            return mInstance;
        }
    
        private RetrofitUtils() {
            initRetrofit();
        }
    
        /**
         * 初始化Retrofit
         */
        private void initRetrofit() {
            OkHttpClient.Builder builder = new OkHttpClient.Builder();
            // 设置超时
            builder.connectTimeout(TIMEOUT, TimeUnit.SECONDS);
            builder.readTimeout(TIMEOUT, TimeUnit.SECONDS);
            builder.writeTimeout(TIMEOUT, TimeUnit.SECONDS);
            OkHttpClient client = builder.build();
            mRetrofit = new Retrofit.Builder()
                    // 设置请求的域名
                    .baseUrl(BASE_URL)
                    // 设置解析转换工厂,用自己定义的
                    .addConverterFactory(ResponseConvert.create())
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .client(client)
                    .build();
        }
    
        /**
         * 创建API
         */
        public <T> T create(Class<T> clazz) {
            return mRetrofit.create(clazz);
        }
    }
    

    代码很简单,创建后台请求接口,调用create即可。

    二、Converter.Factory的封装
    自己采用Gson封装解析。
    /**
     * 自定义Gson解析转换
     */
    
    public class ResponseConvert extends Converter.Factory {
        public static ResponseConvert create() {
            return new ResponseConvert();
        }
    
        /**
         * 转换的方法
         */
        @Override
        public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
            return new BodyConverter<>(type);
        }
    
        private class BodyConverter<T> implements Converter<ResponseBody, T> {
            private Gson gson;
            private Type type;
    
            public BodyConverter(Type type) {
                this.type = type;
                gson = new GsonBuilder()
                        .registerTypeHierarchyAdapter(List.class, new ListTypeAdapter())
                        .create();
            }
    
            @Override
            public T convert(ResponseBody value) throws IOException {
                String json = value.string();
                return gson.fromJson(json, type);
            }
        }
    
        /**
         * 空列表的转换
         */
        private static class ListTypeAdapter implements JsonDeserializer<List<?>> {
            @Override
            public List<?> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
                if (json != null && json.isJsonArray()) {
                    JsonArray array = json.getAsJsonArray();
                    Type itemType = ((ParameterizedType) typeOfT).getActualTypeArguments()[0];
                    java.util.List list = new ArrayList<>();
                    for (int i = 0; i < array.size(); i++) {
                        JsonElement element = array.get(i);
                        Object item = context.deserialize(element, itemType);
                        list.add(item);
                    }
                    return list;
                } else {
                    //和接口类型不符,返回空List
                    return Collections.EMPTY_LIST;
                }
            }
        }
    }
    
    三、Retrofit网络请求基类的封装
    /**
     * 后台统一接口API
     */
    
    public interface ServerApi {
        // 联系人编辑
        @POST(URLS.LOGIN)
        Observable<ResponseBean<LoginBean>> login(@Body RequestBody requestBody);
    }
    
    /**
     * 请求网络业务的基类,AppPresenterr 的封装
     */
    
    public class AppPresenter {
        protected ServerApi mApi = RetrofitUtils.getInstance().create(ServerApi.class);
        private static final Gson gson = new Gson();
    
        /**
         * 1. 转换
         * 统一处理一些动作
         */
        public static <T> void convert(Observable<ResponseBean<T>> observable, Observer<T> observer) {
            observable
                    .map(new Function<ResponseBean<T>, T>() {
                        @Override
                        public T apply(ResponseBean<T> httpResult) throws Exception {
                            // 打印响应的对象
                            LogUtils.object(httpResult);
                            // TODO 实际开发的时候统一处理一些东西
                            if (httpResult == null || httpResult.head == null) {
                                throw new RuntimeException("请求数据异常");
                            } else if (!"1".equals(httpResult.head.bcode)) {
                                throw new RuntimeException(httpResult.head.bmessage);
                            }
                            return httpResult.data;
                        }
                    })
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(observer);
        }
    
        /**
         *  2. 执行的方法
         */
        public static <T> void execute(Observable<ResponseBean<T>> observable, Observer<ResponseBean<T>> observer) {
            observable.subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(observer);
        }
    
        /**
         * 3.请求数据是Json,Json转成RequestBody
         */
        public static RequestBody createRequestBody(Object obj) {
            RequestBean bean = new RequestBean<>(obj);
            String json = gson.toJson(bean);
            // 打印请求的Json
            LogUtils.json(json);
            RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json);
            return body;
        }
    
    }
    有三个通用的方法:
      1.convert方法,转换、统一处理网络请求,将公共处理部分放在这方法里面。
      2.execute方法,只执行,不做任何处理操作,适用于一些不能统一处理的接口。
      3.createRequestBody方法,就是统一创建请求的RequestBody。
    

    如有些代码看不懂,请看:
    Retrofit网络请求,数据的封装(一)

    四、具体网络请求业务类
    /**
     * 登录的业务类
     */
    
    public class LoginPresenter extends AppPresenter {
        /**
         * 登录的接口
         */
        public void login(LoginData data, Observer<LoginBean> observer) {
            Observable<ResponseBean<LoginBean>> login = mApi.login(createRequestBody(data));
            // 转换
            convert(login, observer);
        }
    }
    
    五、测试和使用
    /**
     * 调用登录接口
     */
    public void open(View view) {
        LoginData loginData = new LoginData("135****5219", "12***56");
        presenter.login(loginData, new DialogObserver<LoginBean>(getAppActivity()) {
            @Override
            public void onNext(LoginBean data) {
                // TODO 做登录的成功的操作
                Toast.makeText(getAppActivity(), "" + data.userInfo.nickName, Toast.LENGTH_SHORT).show();
            }
        });
    }
    
    六、补充,对于Observer<T>需要再次封装。
    1.如调用登录要显示Dialog
    2.如Activity销毁要取消请求。
    3.结合加载数据各种状态页面,如:加载中、加载失败、网络异常、数据为空等等
      这些都是可以统一封装在Observer<T>里面。
    

    相关文章

      网友评论

        本文标题:Retrofit网络请求,工具类的封装(二)。

        本文链接:https://www.haomeiwen.com/subject/eovuaxtx.html