Retrofit+RxJava+OkHttp项目中的使用

近来比较火的网络框架,自己项目中已经使用了,

1.Retrofit简单的一句话就是通过通过代理方式和注解转换成一个serviceMethod然后调用callFactory执行的okhttp3.Callt得到返回的数据serviceMethod.callAdapter.adapt(okHttpCall)来产生method所定义的返回值。

简单使用

注解请求方式用途
@PathGET用于替换Url路径中的变量字符
@QueryGET用于拼接在Url路径后的查询参数,但相对于直接在Url后拼接,@Query则是添加一个变量
@QueryMapGET效果等同于多个@Query 参数为Map类型
@FormUrlEncoded/@FieldPOST@FormUrlEncoded修饰表单域,每个表单域子件key-value采用@Field修饰
@BodyPOST可以指定一个对象作为HTTP请求体@Body
@FormUrlEncoded/@FieldPUT@FormUrlEncoded修饰表单域,每个表单域子件key-value采用@Field修饰
@HTTP/@BodyDELETE@HTTP修饰表单域,以指定一个对象作为HTTP请求体@Body,此时表单域一定要写上hasBody = true
@Multipart/@Part或者@PartMapPOST文件上传使用,@Multipart修饰表单域,参数@Part修饰或者参数使用@PartMap

上面就是常用的注解

第一步


第二步
创建retrofit 对像



 private static Retrofit getRetrofit() {
        if (retrofit == null) {
            synchronized (Http.class) {
                if (retrofit == null) {
                    //添加一个log拦截器,打印所有的log
                    HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
                    //可以设置请求过滤的水平,body,basic,headers
                    httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
                    //设置 请求的缓存的大小跟位置
                    File cacheFile = new File(MyApplication.getInstance().getmContext().getCacheDir(), "cache");
                    Cache cache = new Cache(cacheFile, 1024 * 1024 * 50); //50Mb 缓存的大小
                    client = new OkHttpClient
                            .Builder()
                            .addInterceptor(addQueryParameterInterceptor())  //参数添加
                            .addInterceptor(addHeaderInterceptor()) // token过滤
                            .addInterceptor(httpLoggingInterceptor) //日志,所有的请求响应度看到
                            .addInterceptor(addCacheInterceptor())//缓存信息
                            .cache(cache)  //添加缓存
                            .connectTimeout(12, TimeUnit.SECONDS)
                            .readTimeout(12, TimeUnit.SECONDS)
                            .writeTimeout(12, TimeUnit.SECONDS)
                            .build();


                    // 获取retrofit的实例
                    retrofit = new Retrofit
                            .Builder()
                            .baseUrl(UrlHelper.BASE_URL)  //自己配置
                            .client(client)
                            .addConverterFactory(ResponseConverterFactory.create())
                            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                            .build();
                }
            }
        }
        return retrofit;
    }

 在这一步的时候你可以常用信息放在里面作为头部信息,在这里用到了单例模式.

第三步

 创建api 接口


加上@GET 标签,标签后面是这个接口的 尾址sign/login,完整的地址应该是 baseUrl+尾址 ,参数 使用@Query标签,如果参数多的话可以用@QueryMap标 签,接收一个Map。

常见的post请求和GET请求方式,如果要传的表单形式记得要加上 @Multipart 同时注解里面@Part List<MultipartBody.Part> partList 这种方式就是常见的图片和文字上传。

从第二步可以看出创建http请求类,并在里面初始化并配置Retrofit和OkHttp: 同时采用建造者模式添加拦截比如addQueryParameterInterceptor(),addHeaderInterceptor(),

addQueryParameterInterceptor()类中:


这里设置基本信息,当hain.proceed(request)时表示进行okhttp下一步操作

addHeaderInterceptor()


设置头的基本信息。

第四步进行数据返回,在返回时做些处理重新ResponseConverterFactory extends Converter.Factory 为什么处理呢?因为后台返回来的数据有时返回有问题,


然后 通过GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> 这样子的话我直接可以得到返回的值。

public class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
    private final Type type;


    public GsonResponseBodyConverter(Gson gson, Type type) {
        this.type = type;
    }


    /**
     * @param value
     * @return
     * @throws IOException
     */
    @Override
    public T convert(ResponseBody value) {
        int  errorCode=0;
        String  errorMesage="";
        try {
            String result = value.string();
            JSONObject jsonObject = new JSONObject(result);
            if (ConstantUrl.IS_DENCRYPT) {
                String datas = jsonObject.optString("sign");
                if(jsonObject.optInt("error_code") != ConstantUrl.error_code1){
                    jsonObject = new JSONObject(AESUtils.decrypt(datas));
                }
            }
            if ((jsonObject.optInt("error_code") ==ConstantUrl.error_code3)||(jsonObject.optInt("error_code") == ConstantUrl.error_code2)) {
                String data = jsonObject.optString("data");
                //常规数据请求接口数据
                if (!TextUtils.isEmpty(data) && !data.equals("null")) {
                    if(type != String.class){
                        return new Gson().fromJson(data,type);
                    }else{
                        return (T)data;
                    }
                } else {
                    //data里面没有数据
                    errorCode=jsonObject.optInt("error_code");
                    errorMesage=jsonObject.optString("error_message");
                    throw new ResultException(jsonObject.optInt("error_code"), jsonObject.optString("error_message"));
                }
            } else {
                //ErrResponse 将msg解析为异常消息文本
                errorCode=jsonObject.optInt("error_code");
                errorMesage=jsonObject.optString("error_message");
                throw new ResultException(jsonObject.optInt("error_code"), jsonObject.optString("error_message"));
            }
        } catch (IOException e) {
            throw new ResultException(0, UiUtils.getString(R.string.httpSubmitContextNull));
        } catch (JSONException e) {
            throw new ResultException(0, UiUtils.getString(R.string.JsonSyntaxException));
        } catch (RuntimeException e) {
            ErrResponse errResponse = new ErrResponse();
            errResponse.setMsg(UiUtils.getString(R.string.systemExpire));
            throw new ResultException(errorCode, errorMesage);
        }
    }

通过gson 方式把数据转换成自己想要的,这个时候自己定义Exception处理类,


数据返回第二步 通过Rxjava把数据带回,Exception处理分为2部分,本身Exception和服务器返回的Exception,

分开处理,

public abstract class AbsAPICallback<T> extends Subscriber<T> {
    protected  Context mContext;
    private ProgressBarDialog dialog = null;
    public  AbsAPICallback(Context context,boolean isLoadProgress) {
        this.mContext = context;
        if(isLoadProgress && dialog == null){
            dialog = new ProgressBarDialog(context);
        }
        if(isLoadProgress && dialog!=null){
            dialog.showProgress();
        }
    }


    @Override
    public void onError(Throwable e) {
        if(dialog!=null&&dialog.isShowing()){
            dialog.closeProgress();
        }
        Log.e("e","httpException = " +e);
        Throwable throwable = e;
        //获取最根源的异常
        while (throwable.getCause() != null) {
            e = throwable;
            throwable = throwable.getCause();
        }
        if (e instanceof HttpException) {//HTTP错误
            HttpException httpException = (HttpException) e;
            switch (httpException.code()) {
                case IntegerUtil.ABS_UNAUTHORIZED:
                    break;
                case IntegerUtil.ABS_FORBIDDEN:
                    break;
                case IntegerUtil.ABS_NOT_FOUND:
                    ToastUtil.showShort(UiUtils.getString(R.string.noNetWork));
                    break;
                case IntegerUtil.ABS_REQUEST_TIMEOUT:
                    ToastUtil.showShort(UiUtils.getString(R.string.timeout));
                    break;
                case IntegerUtil.ABS_GATEWAY_TIMEOUT:
                    ToastUtil.showShort(UiUtils.getString(R.string.timeout));
                    break;
                case IntegerUtil.ABS_INTERNAL_SERVER_ERROR:
                    break;
                case IntegerUtil.ABS_BAD_GATEWAY:
                    break;
                case IntegerUtil.ABS_SERVICE_UNAVAILABLE:
                    ToastUtil.showShort(UiUtils.getString(R.string.unavailable));
                    break;
                default:
                    LogUtils.d(UiUtils.getString(R.string.InternalServerError));
                    break;
            }
        } else if (e instanceof SocketTimeoutException) {
            String message = UiUtils.getString(R.string.timeout);
            ToastUtil.showShort(message);
            ResultException resultException = new ResultException(0,message);
            onResultError(resultException);
        } else if (e instanceof ResultException) {//服务器返回的错误
            ResultException resultException = (ResultException) e;
            switchError(resultException);
        } else if (e instanceof JsonParseException || e instanceof JSONException || e instanceof ParseException) {
            LogUtils.d(UiUtils.getString(R.string.JsonSyntaxException));
        } else if(e instanceof ConnectException){
            String message = UiUtils.getString(R.string.noNetWork);
            ToastUtil.showShort(message);
            ResultException resultException = new ResultException(0,message);
            onResultError(resultException);
        }
    }
    /**
     * 服务器返回的错误
     */
    protected abstract void onResultError(ResultException ex);


    protected abstract void onDone(T t);


    @Override
    public void onCompleted() {


    }
    private ConfirmDialog comfirmDialog;
    private void switchError(ResultException resultException){
        switch (resultException.getErrCode()){
            case IntegerUtil.ABS_TOKEN_FAIL://您的账号登录异常,请重新登录!
                ToastUtil.showShort(UiUtils.getString(R.string.tokenVerifyFail));
            
                break;


            case IntegerUtil.ABS_TOKEN_EXPIRE://您的账号已过期,为确保信息安全,请重新登录!
                FragmentManager mamage = ((AppCompatActivity) mContext).getSupportFragmentManager();
                if(comfirmDialog==null)
                    comfirmDialog = ConfirmDialog.newInstance("", UiUtils.getString( R.string.tokenVerifyExpire) , "稍后再说", "立即登录");
                if(comfirmDialog.isVisible())
                    return;
                comfirmDialog.setMargin(60)
                        .setWidth(SystemInfoUtil.getScreenWidth()*2/3)
                        .setOutCancel(false)
                        .show(mamage);
                comfirmDialog.setConfirmDialogListener(new ConfirmDialog.ConfirmDialogListener(){
                    @Override
                    public void dialogStatus(int id) {
                        switch (id){
                            case R.id.cancel:
                                //取消 到首页
                          
                                break;


                            case R.id.ok:
                           
                                break;
                        }
                    }
                });
                break;


            case IntegerUtil.ABS_TOKEN_POST_NULL://请求token不能为空            
                break;
            default:
                onResultError(resultException);
                break;


        }
    }


    @Override
    public void onNext(T t) {
        onDone(t);
        if(dialog!=null&&dialog.isShowing()){
            dialog.closeProgress();
        }
    }

最后一步,调用实现

   HttpService httpService = Http.getHttpService();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("courseId", courseId);
        httpService.payDirectInfo(RequestBodyUtils.setRequestBody(map))
                .subscribeOn(Schedulers.io())
                .observeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new AbsAPICallback<PayDirectInfo>(mContext, true) {
                    @Override
                    protected void onDone(PayDirectInfo strTeacher) {

                   


                    }


                    @Override
                    public void onResultError(ResultException ex) {
                        ToastUtil.showToast(ex.getMessage());
                    }
                });


    }


有问题,请随时留言或加本人QQ:874993467

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章