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

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