美文网首页Net
Android Rxjava2+Retrofit2 网络请求封装

Android Rxjava2+Retrofit2 网络请求封装

作者: 我王汉三又回来了 | 来源:发表于2017-08-15 16:33 被阅读911次

    首先列一下本篇文章要实现的功能
    1.对服务器返回的数据进行预处理
    2.请求时带上加载对话框,对话框取消同时取消请求

    一下以个人公司返回数据为例,先上返回实体:

    返回结果集基类 返回分页结果集基类

    这里加一句如果返回分页数据也是要被BaseModel包裹的 BaseModel<PageModel<T>> T可以是所有对象这个你们应该懂得,分页的话T一般是List<你的对象>。

    接下来举个例子
    1.创建Retrofit 数据请求类

    public class SystemApi {
        //超时时间
        public static final int DEFAULT_TIMEOUT = 10;
        private static Retrofit provideRetrofit() {
            OkHttpClient client = new OkHttpClient.Builder()
                    .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                    .writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                    .readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                    .build();
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(BuildConfig.SERVER_HOST)//服务器项目地址
                    .addConverterFactory(JsonConverterFactory.create())//数据转换器,重写了下面有代码
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .client(client)
                    .build();
            return retrofit;
        }
    
        public static SystemApiService provideService() {
            return provideRetrofit().create(SystemApiService.class);
        }
    }
    

    2.数据转换器重写 实现指哪打哪的效果 我要什么结果就什么结果 不给就报错去吧!!!自带的不满足我,具体什么原因忘记了,反正就重写了。

    public class JsonConverterFactory extends Converter.Factory {
    
        private final Gson gson;
    
        private JsonConverterFactory(Gson gson) {
            if (gson == null)
                throw new NullPointerException("gson == null");
            this.gson = gson;
        }
    
        public static JsonConverterFactory create() {
            return create(new Gson());
        }
    
        public static JsonConverterFactory create(Gson gson) {
            return new JsonConverterFactory(gson);
        }
    
        @Override
        public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
            TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
            return new JsonResponseBodyConverter<>(gson, adapter);
        }
    
        @Override
        public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
            TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
            return new JsonRequestBodyConverter<>(gson, adapter);
        }
    }
    

    接下来实现 response和request转换

    final class JsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
        private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
        private static final Charset UTF_8 = Charset.forName("UTF-8");
    
        private final Gson gson;
        private final TypeAdapter<T> adapter;
    
        JsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
            this.gson = gson;
            this.adapter = adapter;
        }
    
        @Override
        public RequestBody convert(T value) throws IOException {
            Buffer buffer = new Buffer();
            Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
            JsonWriter jsonWriter = gson.newJsonWriter(writer);
            adapter.write(jsonWriter, value);
            jsonWriter.close();
            return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
        }
    }
    
    public final class JsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
        private final Gson gson;
        private final TypeAdapter<T> adapter;
        public final static String JSON_ERROR_STR = "数据结构异常!";
    
    
        JsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
            this.gson = gson;
            this.adapter = adapter;
        }
    
        @Override
        public T convert(ResponseBody value) throws IOException {
            String response = value.string();
            if (BuildConfig.DEBUG) {
                LogUtil.i("NetData", response);
            }
            try {
                InputStream inputStream = new ByteArrayInputStream(response.getBytes());
                Reader reader = new InputStreamReader(inputStream);
                JsonReader jsonReader = gson.newJsonReader(reader);
                T t = adapter.read(jsonReader);
                return t;
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException(JSON_ERROR_STR);
            } finally {
                value.close();
            }
    
    
        }
    }
    

    到这里底层的数据请求转换就完成了,接下来我们用 RxJava2 方式去请求一个接口

    public interface SystemApiService {
    
        //去服务器验证账号是否存在,这里就不j介绍更多返回结果了,反正如果是登陆就返回Observable<BaseModel<UserInfo>>,
        //如果是获取用户列表分页就是Observable<PageModel<List<UserInfo>>>
        @FormUrlEncoded
        @POST("authUserName")
        Observable<BaseModel<Boolean>> authUserName(@FieldMap Map<String, Object> params);
    
    }
    

    接下来关键代码来了,结果预处理,不多少说直接上代码,我这前面不写文章的,写了你们也看不懂。

    public class RxHelper {
        /**
         * 对结果进行预处理
         *
         * @param <T>
         * @return
         */
        public static final <T> ObservableTransformer<BaseModel<T>, T> applySchedulers() {
            return new ObservableTransformer<BaseModel<T>, T>() {
                @Override
                public ObservableSource apply(Observable upstream) {
                    return upstream.flatMap(new Function<BaseModel<T>, Observable<T>>() {
                        @Override
                        public Observable<T> apply(BaseModel<T> result) {
                            if (result.ifSuccess()) {//检查是否掉接口成功了
                                return createData(result.getData());//成功,剥取我们要的数据,把BaseModel丢掉
                            } else {
                                return Observable.error(new Exception(result.getMsg()));//出错就返回服务器错误
                            }
                        }
                    }).subscribeOn(Schedulers.io())
                            .unsubscribeOn(Schedulers.io())
                            .observeOn(AndroidSchedulers.mainThread());
                }
            };
        }
    
        /**
         * 创建成功的数据
         *
         * @param data
         * @param <T>
         * @return
         */
        private static <T> Observable<T> createData(final T data) {
            return Observable.create(new ObservableOnSubscribe<T>() {
                @Override
                public void subscribe(@NonNull ObservableEmitter<T> subscriber) throws Exception {
                    try {
                        subscriber.onNext(data);
                        subscriber.onComplete();
                    } catch (Exception e) {
                        subscriber.onError(e);
                    }
                }
            });
        }
    }
    

    预处理就这么完了,我语言组织能力几乎为0,代码总看的来吧。
    开始下一步,对话框显示。怎么弄,很简单继续看代码,要我描述做不到,最多代码给你们稍微注释下

    //实现Observer类,把里面用不到的方法这里全处理掉 我们只处理结果 成功/失败
    public abstract class RxSubscribe<T> implements Observer<T> {
        private Context mContext;
        private ProgressDialog dialog;
        private String msg;
        private boolean isShow = false;
    
        public RxSubscribe(Context context) {
            this.mContext = context;
        }
    
        public RxSubscribe(Context context, boolean isShow) {
            this.mContext = context;
            this.isShow = isShow;
            msg = mContext.getString(R.string.dialog_message_loading);
        }
    
    
        public RxSubscribe(Context context, int msgResId) {
            this.mContext = context;
            isShow = true;
            msg = mContext.getString(msgResId);
        }
    
    
        @Override
        public void onComplete() {
            if (isShow) {
                if (dialog != null)
                    dialog.dismiss();
            }
        }
    
        @Override
        public void onSubscribe(@NonNull final Disposable d) {
            if (isShow) {
                dialog = new ProgressDialog(mContext);
                dialog.setMessage(msg);
                dialog.setIndeterminate(true);
                dialog.setCanceledOnTouchOutside(false);
                dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
                    @Override
                    public void onCancel(DialogInterface dialogInterface) {
                     // 对话框取消 直接停止执行请求
                        if (!d.isDisposed()) {
                            d.dispose();
                        }
                    }
                });
                dialog.show();
    
            }
        }
    
        @Override
        public void onNext(T t) {
            _onNext(t);
        }
    
        @Override
        public void onError(Throwable e) {
            Log.i("onError",e.getMessage() );
           //把底层的一些错误翻译一下用户看不来
            if (e.getMessage() == null || e.getMessage().isEmpty()) {//未知错误
                _onError(mContext.getString(R.string.error_unknown));
            } else if (e.getMessage().contains("Failed to connect to") ||
                    e.getMessage().contains("failed to connect to")) {//连接服务器失败
                if (!SystemUtil.isNetworkAvailable(mContext)) {//没网络
                    _onError(mContext.getString(R.string.error_bad_network));
                } else {//真的没连接上服务器
                    _onError(mContext.getString(R.string.error_connect_server));
                }
            } else if (e.getMessage().contains("timed out") || e.getMessage().contains("timeout")) {
              //超时了
                _onError(mContext.getString(R.string.error_connect_server_timeout));
            }else if (e.getMessage().contains("500")) {
                //服务器内部错误
                _onError(mContext.getString(R.string.error_connect_server_timeout));
            } else {
                _onError(e.getMessage());
            }
            if (isShow) {
                if (dialog != null)
                    dialog.dismiss();
            }
        }
        //成功  
        protected abstract void _onNext(T t);
        //失败
        protected abstract void _onError(String message);
    }
    

    基础的处理全部完成 最后我们的代码就是请求接口好了

    /**
     * Created by 王汗三
     * Date 2017/7/14.
     */
    
    public class RegisterPresenter extends BasePresenter {
        private RegisterActivity activity;
    
        public RegisterPresenter(RegisterActivity activity) {
            super(activity);
            this.activity = activity;
        }
    
    
        public void authUserName(String username) {
            params.put("username", username);
            SystemApi.provideService().authUserName(params).compose(RxHelper.<Boolean>applySchedulers()).subscribe(new RxSubscribe<Boolean>(activity, R.string.dialog_message_auth) {
                @Override
                protected void _onNext(Boolean isExits) {
                    if (isExits) {
                        IToast.show(context, "用户名已被别家熊孩子抢走了!");
                    } else {
                        activity.gotoNext();
                    }
                }
    
                @Override
                protected void _onError(String message) {
                    IToast.show(context, message);
                }
            });
        }
    
    }
    

    好了差不多完成了,最后给大家附带给上传文件的 看🐴 不多说

        //上传文件加参数
        @Multipart
        @POST("PostThreads")
        Observable<BaseModel<String>> uploadPost(@Part List<MultipartBody.Part> parts);
    

    在带上个工具类

    public class MultipartBodyUtil {
    
        public static List<MultipartBody.Part> files2Parts(Map<String, String> fileMaps,
                                                           MediaType imageType) {
            List<MultipartBody.Part> parts = new ArrayList<>();
            for (Map.Entry<String, String> entry : fileMaps.entrySet()) {
                File file = new File(entry.getValue());
                RequestBody requestBody = RequestBody.create(imageType, file);
                // 将RequestBody封装成MultipartBody.Part类型(同样是okhttp的)
                MultipartBody.Part part = MultipartBody.Part.
                        createFormData(entry.getKey(), file.getName(), requestBody);
                // 添加进集合
                parts.add(part);
            }
            return parts;
        }
    
    
    
        /**
         * 直接添加文本类型的Part到的MultipartBody的Part集合中
         *
         * @param parts Part集合
         * @param key   参数名(name属性)
         * @param value 文本内容
         */
        public static void addTextPart(List<MultipartBody.Part> parts,
                                       String key, String value) {
                if(value!=null) {
                    RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain;charset=utf-8"), value);
                    MultipartBody.Part part = MultipartBody.Part.createFormData(key, null, requestBody);
                    parts.add(part);
                }
        }
    }
    

    最后请求

    /**
     * Created by 王汗三
     * Date 2017/2/7.
     */
    
    public class SentPostPresenter extends BasePresenter {
        SentPostActivity activity;
    
        public SentPostPresenter(SentPostActivity activity) {
            super(activity);
            this.activity = activity;
        }
    
        public void uploadPost(String travelID, String forumId, String title, List<EditData> editDataList) {
            Map<String, String> fileMaps = new HashMap<>();
            for (int i = 0; i < editDataList.size(); i++) {
                if (editDataList.get(i).getImagePath() != null && !editDataList.get(i).getImagePath().isEmpty()) {
                    fileMaps.put("file" + (i + 1), editDataList.get(i).getImagePath());
                }
            }
            List<MultipartBody.Part> parts = MultipartBodyUtil.files2Parts(fileMaps, MediaType.parse("image/*;charset=utf-8"));
            addBasePart(parts);//这个是我们项目必传参数 你们可以不用管
            MultipartBodyUtil.addTextPart(parts, "eventId", travelID);
            MultipartBodyUtil.addTextPart(parts, "forumId", forumId);
            MultipartBodyUtil.addTextPart(parts, "title", title);
            String content=new JsonResolver<List<EditData>>() {
            }.toJson(editDataList);
            MultipartBodyUtil.addTextPart(parts, "content", content);
            SystemApi.provideService().uploadPost(parts).compose(RxHelper.<String>handleResult()).subscribe(new RxSubscribe<String>(activity, R.string.dialog_message_submit) {
                @Override
                protected void _onNext(String s) {
                    IToast.show(activity, "发表成功");
                    activity.setResult(Activity.RESULT_OK);
                    activity.finish();
                }
    
                @Override
                protected void _onError(String message) {
                    Log.i("_onError",message);
                    IToast.show(activity, message);
                }
            });
    
        }
    }
    

    这篇文章就到这里 别人说授人以鱼不如授人以渔,但是我只会授鱼,吃着鱼领悟吧! 看不懂去看看Rxjava和泛型基础。
    本文引用第三方库:
    compile 'io.reactivex.rxjava2:rxjava:2.0.7'
    compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
    compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
    compile 'com.squareup.retrofit2:retrofit:2.3.0'
    compile 'com.squareup.okio:okio:1.13.0'
    compile 'com.squareup.okhttp3:okhttp:3.8.1'
    compile 'com.google.code.gson:gson:2.8.0'

    相关文章

      网友评论

      本文标题:Android Rxjava2+Retrofit2 网络请求封装

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