手记

如何去封装okhttp请求

我们来看一个正常的okhttp请求:

OkHttpClient client = new OkHttpClient();
RequestBody body = new FormBody.Builder()
        .add("bookid",String.valueOf(mBook.bookid))
        .add("bookName",mBookNameEdit.getText().toString()).build();

final Request request = new Request.Builder()
        .url("http://139.199.89.89/api/v1/books")
        .post(body).build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        Log.d(TAG,"<<<<e="+e);

    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        if(response.isSuccessful()) {
            String d = response.body().string();
            Log.d(TAG,"<<<<d="+d);
        }
    }
});

这个有什么问题呢,第一个这个callback肯定是子线程,我们在onResponse里不能去更新UI,

还有如果对于每一个请求都要写这么一段,显得很繁琐,不够简洁,如果想往url加入一些公共参数,

显然这个也是不能实现的

那么下面我们就来封装一下这个接口:我们首先需要继承这个callback

public abstract class OkHttpResJsonHandler extends OkHttpCallback<JSONObject> {

    @Override
    protected JSONObject parseResponse(Response response) throws Throwable {
        return responseToJson(response);
    }
}
private OkHttpResJsonHandler mSendListener = new OkHttpResJsonHandler() {

    @Override
    protected boolean isPostMainThread() {
        return isBackMainThread();
    }

    @Override
    public void onSuccess(Call call, int statusCode, Headers headers, JSONObject response) {
        if (null != response) {
            String status = response.optString(STATUS);
            String statusMessage = response.optString(MESSAGE);

            if (TextUtils.isEmpty(statusMessage)) {
                setStatus(status, ApiStatus.getStatusMessage(status));
            } else {
                setStatus(status, statusMessage);
            }

            if (isSuccess()) {
                try {
                    dismissLoading();
                    onParse(response);
                    if (null != mApiListener) {
                        mApiListener.success(ApiUtil.this);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    failure(API_STATUS_PARSE_ERROR, mContext.getString(R.string.parse_error));
                }
            } else {
                if ("failed".equals(getStatus())) {
                    // 兼容data里含有message字段的api 优先级最高
                    JSONObject data = response.optJSONObject(DATA);
                    if (data != null) {
                        String message = data.optString(MESSAGE);
                        if (!TextUtils.isEmpty(message)) {
                            failure(status, message);
                        } else {
                            message = response.optString(MESSAGE);
                            if (!TextUtils.isEmpty(message)) {
                                failure(status, message);
                            } else {
                                failure(status, getStatusMessage());
                            }
                        }
                    }
                }
            }
        } else {
            failure(API_STATUS_PARSE_ERROR, mContext.getString(R.string.parse_error));
        }
    }

    @Override
    public void onFailure(Call call, int code, Headers headers, int error, Throwable t) {
        if (code == 403) {
            failure(API_STATUS_REJECT_ERROR, "系统繁忙,请稍后再试");
        } else if (error == OkHttpCallback.RESPONSE_ERROR_SERVER) {
            failure(API_STATUS_NET_ERROR, "服务器处理错误");
        } else if (error == OkHttpCallback.RESPONSE_ERROR_TIMEOUT) {
            failure(API_STATUS_TIMEOUT, "服务器处理错误");
        } else if (error == OkHttpCallback.RESPONSE_CANCELED) {
            failure(API_STATUS_CANCELED, "请求取消");
        } else {
            failure(API_STATUS_NET_ERROR, "亲,您的网络不给力!");
        }
    }
};

建一个OKHttpUtil:

public static <T> void post(String url, OkRequestParams postBodyParams, Object tag, boolean isProgress, boolean commonParams, OkHttpCallback<T> okHttpCallback) {
    //这里可以添加公共参数
    if (commonParams) {
        OkRequestParams urlComParams = new OkRequestParams();
        url = getFinalUrl(url, urlComParams);
    } else {
        url = getFinalUrl(url, postBodyParams);
    }

    Call call = null;
    Callback callback = getCallBack(okHttpCallback);
    try {
        RequestBody requestBody = (postBodyParams == null ? null : postBodyParams.getRequestBody());
        Headers headers = (postBodyParams == null ? null : postBodyParams.getRequestHeaders());
        Request request = getRequest(url, requestBody, headers, tag);

        call = mOkHttpClient.newCall(request);


        call.enqueue(callback);
    } catch (Throwable e) {
        e.printStackTrace();
        callback.onFailure(call, new IOException("post", e));
    }
}

public static Request getRequest(String url, RequestBody requestBody, Headers headers, Object tag) {
    Request.Builder builder = new Request.Builder();

    if (requestBody != null) {
        builder.post(requestBody);
    }
    if (headers != null) {
        builder.headers(headers);
    }
    if (tag != null) {
        builder.tag(tag);
    }
    builder.url(url);
    return builder.build();
}

我们这样写api:

public class TestGetBookApi extends ApiUtil {

    public String mData;

    public TestGetBookApi() {
        super();
    }

    @Override
    protected String getUrl() {
        return "http://139.199.89.89/api/v1/books";
    }

    @Override
    protected  void parseData(JSONObject jsonObject) throws Exception {
        mData = jsonObject.optString(DATA);
    }
}

调用地方:

private void proceedBookApi() {
    new TestGetBookApi().get(this, "loading", true, false, new ApiListener(){

        @Override
        public void success(ApiUtil api) {
            Log.d(TAG,"<<<<<<success");
            TestGetBookApi api1 = (TestGetBookApi)api;
            if(api1.mData != null) {
                mBookArrayList = new Gson().fromJson(api1.mData, new TypeToken<List<Book>>(){}.getType());
                mBookMainAdapter.setList(mBookArrayList);
            }
        }

        @Override
        public void failure(ApiUtil api) {
            Log.d(TAG,"<<<<<<failure");

        }
    });
}

主体ApiUtil的完整代码是:

public abstract class ApiUtil {

    public static final String API_STATUS_REJECT_ERROR = "RejectError";
    public static final String API_STATUS_NET_ERROR = "NetError";
    public static final String API_STATUS_PARSE_ERROR = "ParseError";
    public static final String API_STATUS_NONLOGIN = "nonLogin";
    public static final String API_STATUS_TIMEOUT = "timeout";
    public static final String API_STATUS_CANCELED = "canceled";

    private static final int STATUS_CODE_NO_NETWORK_PRE_HTTP = -1001; // 无网络状态码(不发送联网请求)

    /**
     * 请求参数列表
     */
    private OkRequestParams mParams = new OkRequestParams();

    /**
     * 标签,用于扩展保存标识信息
     */
    private Object mTag = null;

    /**
     * 状态码
     */
    private String mStatus = "";
    /**
     * 状态码信息
     */
    private String mStatusMessage = "";

    /**
     * 上下文
     */
    private Context mContext = null;
    /**
     * 是否显示加载界面
     */
    private boolean mShowLoading = true;
    /**
     * 数据返回后是否清除加载界面
     */
    private boolean mDismissLoadingFinished = true;
    /**
     * 加载界面字符串
     */
    private String mLoadingString = null;
    /**
     * 是否显示状态信息
     */
    private boolean mShowStatusMessage = true;
    /**
     * API发送监听
     */
    private ApiListener mApiListener = null;

    /**
     * 是否返回主线程
     *
     * @return 默认为true; 如果子类重写返回false,则不允许更新ui,且不能Toast
     */
    protected boolean isBackMainThread() {
        return true;
    }

    /**
     * 发送监听
     */
    private OkHttpResJsonHandler mSendListener = new OkHttpResJsonHandler() {

        @Override
        protected boolean isPostMainThread() {
            return isBackMainThread();
        }

        @Override
        public void onSuccess(Call call, int statusCode, Headers headers, JSONObject response) {
            if (null != response) {
                String status = response.optString(STATUS);
                String statusMessage = response.optString(MESSAGE);

                if (TextUtils.isEmpty(statusMessage)) {
                    setStatus(status, ApiStatus.getStatusMessage(status));
                } else {
                    setStatus(status, statusMessage);
                }

                if (isSuccess()) {
                    try {
                        dismissLoading();
                        onParse(response);
                        if (null != mApiListener) {
                            mApiListener.success(ApiUtil.this);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        failure(API_STATUS_PARSE_ERROR, mContext.getString(R.string.parse_error));
                    }
                } else {
                    if ("failed".equals(getStatus())) {
                        // 兼容data里含有message字段的api 优先级最高
                        JSONObject data = response.optJSONObject(DATA);
                        if (data != null) {
                            String message = data.optString(MESSAGE);
                            if (!TextUtils.isEmpty(message)) {
                                failure(status, message);
                            } else {
                                message = response.optString(MESSAGE);
                                if (!TextUtils.isEmpty(message)) {
                                    failure(status, message);
                                } else {
                                    failure(status, getStatusMessage());
                                }
                            }
                        }
                    }
                }
            } else {
                failure(API_STATUS_PARSE_ERROR, mContext.getString(R.string.parse_error));
            }
        }

        @Override
        public void onFailure(Call call, int code, Headers headers, int error, Throwable t) {
            if (code == 403) {
                failure(API_STATUS_REJECT_ERROR, "系统繁忙,请稍后再试");
            } else if (error == OkHttpCallback.RESPONSE_ERROR_SERVER) {
                failure(API_STATUS_NET_ERROR, "服务器处理错误");
            } else if (error == OkHttpCallback.RESPONSE_ERROR_TIMEOUT) {
                failure(API_STATUS_TIMEOUT, "服务器处理错误");
            } else if (error == OkHttpCallback.RESPONSE_CANCELED) {
                failure(API_STATUS_CANCELED, "请求取消");
            } else {
                failure(API_STATUS_NET_ERROR, "亲,您的网络不给力!");
            }
        }
    };

    private void failure(String status, String statusMessage) {
        dismissLoading();
        setStatus(status, statusMessage);
        // 特殊处理,1、当提示信息为未登陆时不弹出toast提示;  2、请求被取消
        if (!status.equals(API_STATUS_NONLOGIN) && !status.equals(API_STATUS_CANCELED)) {
            showStatusMessage(statusMessage);
        }
        if (null != mApiListener) {
            try {
                mApiListener.failure(ApiUtil.this);
            } catch (Exception e) {
            }
        }
    }


    protected ApiUtil() {
        super();
    }

    public Context getContext() {
        if (mContext == null) {
            return PicApplication.getContext();
        }
        return mContext;
    }


    /**
     * 判断状态码是否成功
     *
     * @return
     */
    public boolean isSuccess() {
        return ApiStatus.isSuccess(getStatus());
    }




    /**
     * 获取状态码
     *
     * @return:状态码
     */
    public String getStatus() {
        return mStatus;
    }

    /**
     * 设置状态码
     *
     * @param status :状态码
     */
    public void setStatus(String status) {
        mStatus = status;
    }

    /**
     * 获取状态信息
     *
     * @return:状态信息
     */
    public String getStatusMessage() {
        return mStatusMessage;
    }


    /**
     * 设置状态码及错误信息
     *
     * @param status        :状态码
     * @param statusMessage :状态信息
     */
    public void setStatus(String status, String statusMessage) {
        mStatus = status;
        mStatusMessage = statusMessage;
    }


    /**
     * 添加参数
     *
     * @param key
     * @param value
     */
    public void addParam(String key, String value) {
        mParams.put(key, value);
    }


    /**
     * 获取url
     * @return:http链接url
     */
    protected abstract String getUrl();



    /**
     * 解析数据
     *
     * @param jsonObject
     */
    private void onParse(JSONObject jsonObject) throws Exception {
        parseData(jsonObject);
    }

    /**
     * 解析数据
     *
     * @param jsonObject
     */
    protected abstract void parseData(JSONObject jsonObject) throws Exception;




    /**
     * http post
     *
     * @param context           :上下文
     * @param loadingString     :加载界面显示的提示文字, 如果传空将不显示加载界面
     * @param dismissLoading    :请求响应后是否销毁加载界面
     * @param showStatusMessage :是否在出错时显示出错信息
     * @param listener          :请求响应监听
     */
    public void post(Context context, String loadingString, boolean dismissLoading, boolean showStatusMessage,
                     ApiListener listener) {
        post(context, !TextUtils.isEmpty(loadingString), loadingString, dismissLoading, showStatusMessage, listener);
    }

    /**
     * http post
     *
     * @param context           :上下文
     * @param showLoading       :是否显示加载界面
     * @param loadingString     :加载界面文字, 如果为空将显示默认文字
     * @param dismissLoading    :请求完成后是否清除加载界面
     * @param showStatusMessage :是否显示出错信息
     * @param listener          :发送回调
     */
    public void post(Context context, boolean showLoading, String loadingString, boolean dismissLoading,
                     boolean showStatusMessage, ApiListener listener) {
        init(context, showLoading, loadingString, dismissLoading, showStatusMessage, listener);
        post();
    }




    /**
     * http get
     *
     * @param context           :上下文
     * @param loadingString     :加载界面显示的提示文字, 如果传空将不显示加载界面
     * @param dismissLoading    :请求响应后是否销毁加载界面
     * @param showStatusMessage :是否在出错时显示出错信息
     * @param listener          :请求响应监听
     */
    public void get(Context context, String loadingString, boolean dismissLoading, boolean showStatusMessage,
                    ApiListener listener) {
        get(context, !TextUtils.isEmpty(loadingString), loadingString, dismissLoading, showStatusMessage, listener);
    }


    /**
     * http get
     *
     * @param context           :上下文
     * @param showLoading       :是否显示加载界面
     * @param loadingString     :加载界面文字, 如果为空将显示默认文字
     * @param dismissLoading    :请求完成后是否清除加载界面
     * @param showStatusMessage :是否显示出错信息
     * @param listener          :发送回调
     */
    public void get(Context context, boolean showLoading, String loadingString, boolean dismissLoading,
                    boolean showStatusMessage, ApiListener listener) {
        init(context, showLoading, loadingString, dismissLoading, showStatusMessage, listener);
        get();
    }

    /**
     * 无网络时模拟失败发送失败消息
     */
    private void post() {

        if (Util.hasNetwork(mContext)) {
            OkHttpUtil.post(getUrl(), mParams, mTag, mSendListener);
        } else if (mSendListener != null) {
            mSendListener.onFailure(null, STATUS_CODE_NO_NETWORK_PRE_HTTP, null, OkHttpCallback.RESPONSE_ERROR_NET, new Throwable("recvfrom failed: ECONNRESET (Connection reset by peer)"));
        }
    }



    /**
     * 无网络时模拟失败发送失败消息
     */
    private void get() {
        if (Util.hasNetwork(mContext)) {
            OkHttpUtil.get(getUrl(), mParams, mTag, mSendListener);
        } else if (mSendListener != null) {
            mSendListener.onFailure(null, STATUS_CODE_NO_NETWORK_PRE_HTTP, null, OkHttpCallback.RESPONSE_ERROR_NET, new Throwable("recvfrom failed: ECONNRESET (Connection reset by peer)"));
        }
    }

    /**
     * 初始化发送请求
     *
     * @param context           :上下文
     * @param showLoading       :是否显示加载界面
     * @param loadingString     :加载界面文字, 如果为空将显示默认文字
     * @param dismissLoading    :请求完成后是否清除加载界面
     * @param showStatusMessage :是否显示出错信息
     * @param listener          :发送回调
     */
    private void init(Context context, boolean showLoading, String loadingString, boolean dismissLoading,
                      boolean showStatusMessage, ApiListener listener) {
        if (null == context) {
            context = PicApplication.getContext();
        }
        mContext = context;
        mApiListener = listener;
        mShowLoading = showLoading;
        mLoadingString = loadingString;
        mDismissLoadingFinished = dismissLoading;
        mShowStatusMessage = showStatusMessage;

        showLoading();
    }

    /**
     * 设置loading对话栏显示信息
     *
     * @return
     */
    protected String getDialogMessage() {
        if (TextUtils.isEmpty(mLoadingString)) {
            return mContext.getString(R.string.loading);
        } else {
            return mLoadingString;
        }
    }

    /**
     * 显示加载界面
     */
    protected void showLoading() {
        if (mShowLoading) {
            DialogUtil.showLoadingDialog(mContext, getDialogMessage());
        }
    }

    /**
     * 清除加载界面
     */
    protected void dismissLoading() {
        // 成功时判断是否清除加载界面,失败时不判断是否清除直接清除加载界面
        if ((!isSuccess()) || mDismissLoadingFinished) {
            DialogUtil.dismissLoadingDialog(mContext);
        }
    }

    /**
     * 显示出错信息
     *
     * @param message
     */
    protected void showStatusMessage(String message) {
        if (mShowStatusMessage && !TextUtils.isEmpty(message)) {
            Toast.makeText(mContext,message,Toast.LENGTH_SHORT).show();
        }
    }

    protected String getString(int resId) {
        String result = "";
        if (null != mContext) {
            result = mContext.getString(resId);
        }
        return result;
    }

}

代码在https://github.com/nickgao1986/StepSport

0人推荐
随时随地看视频
慕课网APP