美文网首页
volley 二次封装,项目实际应用

volley 二次封装,项目实际应用

作者: 木小伍 | 来源:发表于2018-04-16 18:35 被阅读0次

    前言

    volley 出来也这么久了,在这期间,也陆陆续续的出了各种各样的网络请求框架,每一个的框架都说自己是世界上最好的框架,然后拿出其他的框架的劣势来做对比。我个人还是觉得,最好的框架是自己会用的框架,能够满足工作需要的框架就是好框架。

    封装思路

    1.建立全局的网络请求工具类
    2.自定义请求(现在项目大部分都是post请求,所以目前只自定义了json的post请求,string的post请求)
    3.请求的发送,与返回统一封装,一步到位

    结构分析(最底部有完整的项目链接)

    整个demo的结构图如下


    结构图.png

    RequestListener:响应监听接口,负责 response返回后针对业务对象的逻辑处理,主要声明了onSuccess(),onError(),两个方法,如果项目有其他需要可以进行其他操作

    public interface RequestListener {
    
        void onSuccess(String result);
    
        void onError(String printMe);
    }
    

    AbsRequestListener:对RequestListener的再次封装,主要实现的是对onError()方法的统一处理,在使用的时候就不必重写onError()方法了。

    public abstract class AbsRequestListener implements RequestListener {
        @NonNull
        protected Context mContext;
        public AbsRequestListener(Context context) {
            this.mContext = context;
        }
        @Override
        public void onError(String printMe) {
            if (null != mContext)
                Toast.makeText(mContext,printMe,Toast.LENGTH_SHORT).show();
        }
    }
    

    IMErrorListener:错误的回调,对response的onError()方法的重写,错误可能是服务器错误,也可能是volley内部错误,主要方法如下:

     /**
         * 接口返回错误信息,进行相应的操作
         *
         * @param error
         */
        @Override
        public void onErrorResponse(VolleyError error) {
    
            //操作演示
            requestListener.onError(error.getMessage());
    //        LoadingDialog.dismiss();
    //
    //        Resources resources = App.getInstance().getResources();
    //       //错误的类型
    //        this.requestListener.onError(error instanceof TimeoutError ? resources.getString(R.string.net_error_timeout) :
    //                (error instanceof NoConnectionError ? resources.getString(R.string.net_error_noConnection) : resources.getString(R.string.net_error_ununited)));
    //
    //        if (AppConfig.DEBUG && error != null && error.networkResponse != null && error.networkResponse.data != null) {
    //            byte[] htmlBodyBytes = error.networkResponse.data;
    //            if (htmlBodyBytes != null) {
    //                CommonUtils.LOG_D(getClass(), "VolleyError=" + new String(htmlBodyBytes));
    //            }
    //        }
        }
    

    IMJsonListener:(post json方式)成功返回的响应监听类,对成功返回的数据进行二次处理。

        @Override
        public void onResponse(JSONObject response) {
            try {
                //     LoadingDialog.dismiss();
                // 将JSONObject转换成String
                String responseText = response.toString();
                // 获得请求结果
                Resources res = mContext.getResources();
                // 返回对象为NULL、空、以及状态码为-1时
                if (TextUtils.isEmpty(responseText)) {
                    this.requestListener.onError("服务器貌似GG了...");
                    return;
                }
                // 获取状态码
                ResponseInfo responseInfo = JsonUtils.json2Object(responseText, ResponseInfo.class);
                // response不符合规范
                if (null == responseInfo) {
                    this.requestListener.onError("服务器还是GG了");
                    return;
                }
                if (200 == responseInfo.getCode()) { //服务器正常,回调到onsucess方法
                    this.requestListener.onSuccess(JsonUtils.getJSONObjectKeyVal(responseText,"data"));
                }
    //
            } catch (Exception e) {
    //            if (BuildConfig.DEBUG) {//调试模式下直接抛出异常
    //                throw e;
    //            } else {//release环境下提示错误,同时上报异常
    //                this.requestListener.onError(mContext.getResources().getString(R.string.net_error_ununited));
    //                MobclickAgent.reportError(mContext, e);
    //            }
            }
        }
    

    IMStringListener:(post String方式)成功返回的响应监听类,对成功返回的数据进行二次处理。主要代码同上。

    PostJsonRequset:自定义的json 请求。主要重写了getHeaders()方法。
    PostStringRequest:自定义的String请求,主要重写了getHeaders()方法和getParams()方法
    HttpUtil:网络请求的工具类,对volley的封装,请求方式的声明。
    BeanInfo:javaBean 的实体类,接口返回的数据实体类
    ResponseInfo:基本的返回数据的实体类,基本格式如下:

    {
        "code": 200,
        "msg": "成功!",
        "data": [....]
    }
    

    JsonUtils:Gson的工具类,主要用于Javabean 和 json数据的互转。

    封装第一步

    创建HttpUtils,这个类主要声明并实例化了RequestQueue,采用单例模式对外暴露一个静态的方法以获取实例对象,以及规定了方法的实现。
    实例化RequstQueue,创建单利模式的主要代码如下:

       /**
         * 请求队列
         */
        private RequestQueue queue;
        /**
         * 上下文对象
         */
        private Context mContext;
    
        /**
         * 会话识别号
         */
        public static String sessionId = "0000";
    
        private static HttpUtil httpUtil;
    
        /**
         * 构造函数
         *
         * @param context 上下文对象
         */
        private HttpUtil(Context context) {
            queue = Volley.newRequestQueue(context);
            this.mContext = context;
        }
    
        public static HttpUtil getInstance(Context context) {
            if (null == httpUtil) {
                httpUtil = new HttpUtil(context);
            }
            if (context != httpUtil.mContext) {
                httpUtil.cancelAllRequestQueue();
                httpUtil = new HttpUtil(context);
            }
            return httpUtil;
        }
    

    JsonPost请求的声明,适用于服务器端需要的传递参数是jsonObject的数据类型。
    在这里面我们可以添加每个接口必传的参数,如token之类的,添加方法可以参见StringPost方法的声明

       /**
         * postJson请求
         *
         * @param url             服务器地址
         * @param jsonObject      json 对象
         * @param requestListener 请求监听
         * @return
         */
        private Request<JSONObject> doPostByJson(String url, JSONObject jsonObject,
                                                 RequestListener requestListener) {
    
            PostJsonRequset postJsonRequset = new PostJsonRequset(url, jsonObject,
                    new IMJsonListener(requestListener, mContext),
                    new IMErrorListener(requestListener, mContext));
    
            Request<JSONObject> request = queue.add(postJsonRequset);
    
            // 为请求添加context标记
            request.setTag(mContext);
            return request;
        }
    

    StringPost请求的声明,主要适用于服务器端需要的参数是 key - value的形式。
    (一般来说,一个项目通常只会用一种请求方法,要么json,要么string,一般不会两种都出现,如果出现了,可以跟服务器端的聊聊人生了,所以二者JsonPost和StringPost选一个就行了)

     /**
         * postString请求
         *
         * @param url             服务器地址
         * @param params          参数
         * @param requestListener 请求监听
         * @return
         */
        public Request<String> doPostByStr(String url, Map<String, String> params,
                                           RequestListener requestListener) {
    
            //    在每次请求发起之前先进行网络检查
    //        if (!checkNetState(mContext)) {
    //            Toast.makeText(mContext, R.string.net_error_check, Toast.LENGTH_SHORT)
    //                    .show();
    //            return null;
    //        }
    
    //依照实际需求添加固定参数 如token之类的
    //        params.put("appVerison", BuildConfig.VERSION_NAME);
    //        String accessToken = Constants.getAccessToken(mContext);
    //        if (!TextUtils.isEmpty(accessToken)) {
    //            params.put("access_token", accessToken);
    //        }
    
            PostStringRequest postStrRequset = new PostStringRequest(url, params,
                    new IMStringListener(requestListener, mContext),
                    new IMErrorListener(requestListener, mContext));
    
            Request<String> request = queue.add(postStrRequset);
    
            // 为请求添加context标记
            request.setTag(mContext);
            return request;
        }
    

    为了代码的友好,在这里,同样也添加了网络请求的取消方法,可以在BaseActiviy的onStop()或者onDestory()方法中调用

        /**
         * 清除当前activity所有的请求
         */
        public void cancelAllRequestQueue() {
            if (null != queue && null != mContext) {
                queue.cancelAll(mContext);
                queue.start();
                queue = null;
                mContext = null;
                httpUtil = null;
            }
        }
    

    第二步 -- 自定义请求

    自定义PostStringRequst,继承自StringRequst,在这里我我们主要要重写的方法也就三个:
    1.构造函数
    2.重写请求头
    2.重写请求参数
    代码如下:

    /**
     * 作者: 伍跃武
     * 时间: 2018/4/11
     * 描述:psotString 方式请求
     */
    
    public class PostStringRequest extends StringRequest {
    
        /**
         * 请求超时时间
         */
        public static final int SOCKET_TIMEOUT = 60 * 1000;
        /**
         * 最大重新请求次数
         */
        public static final int MAX_RETRIES = 0;
        /**
         * 重新请求权重
         */
        public static final float BACK_OFF = 1.0f;
        /**
         * 字符编码
         */
        public static final String ENCODEING = "UTF-8";
    
    
        //以上代码建议放在全局的常亮类中,作为演示,暂时在这里
    
        private Map<String, String> mParams = new HashMap<>();
    
        public PostStringRequest(String url, Map<String, String> params, Response.Listener<String> listener, Response.ErrorListener errorListener) {
            super(Method.POST, url, listener, errorListener);
            this.mParams = params;
            setRetryPolicy(new DefaultRetryPolicy(SOCKET_TIMEOUT, MAX_RETRIES, BACK_OFF));
        }
        /**
         * 重写请求编码
         *
         * @return
         */
        @Override
        protected String getParamsEncoding() {
            return ENCODEING;
        }
    
        /**
         * 重写请求头
         *
         * @return
         * @throws AuthFailureError
         */
        @Override
        public Map<String, String> getHeaders() throws AuthFailureError {
            Map<String, String> headers = new HashMap<String, String>();
            headers.put("Charsert", getParamsEncoding());
    //        headers.put("Content-Type", "application/json;charset=utf-8");
    //        headers.put("Accept-Encoding", "gzip,deflate");
    //        headers.put("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3");
            return headers;
        }
    
       /**
         * 重写获取参数的方法
         * @return
         */
        @Override
        public Map<String, String> getParams() {
            return mParams;
        }
    }
    

    同样,postJsontRequest需要继承自JsonObjectRequest,同样需要重写以上几个方法(除了getParams()方法),详细代码如下:

    
    /**
     * 作者: 伍跃武
     * 时间: 2018/4/11
     * 描述:自定义参数为json的post请求
     */
    
    public class PostJsonRequset extends JsonObjectRequest {
    
        /**
         * 请求超时时间
         */
        public static final int SOCKET_TIMEOUT = 60 * 1000;
        /**
         * 最大重新请求次数
         */
        public static final int MAX_RETRIES = 0;
        /**
         * 重新请求权重
         */
        public static final float BACK_OFF = 1.0f;
        /**
         * 字符编码
         */
        public static final String ENCODEING = "UTF-8";
    
    
        //以上代码建议放在全局的常亮类中,作为演示,暂时在这里
    
        /**
         * 构造函数
         *
         * @param url           请求链接
         * @param jsonRequest   参数转换成为json对象
         * @param listener      请求成功的监听
         * @param errorListener 请求失败的监听
         */
        public PostJsonRequset(String url, JSONObject jsonRequest, Response.Listener<JSONObject> listener, Response.ErrorListener errorListener) {
            super(Method.POST, url, jsonRequest, listener, errorListener);
            //设置重试策略
            setRetryPolicy(new DefaultRetryPolicy(SOCKET_TIMEOUT, MAX_RETRIES, BACK_OFF));
        }
    
        /**
         * 重写请求编码
         *
         * @return
         */
        @Override
        protected String getParamsEncoding() {
            return ENCODEING;
        }
    
        /**
         * 重写请求头
         *
         * @return
         * @throws AuthFailureError
         */
        @Override
        public Map<String, String> getHeaders() throws AuthFailureError {
            Map<String, String> headers = new HashMap<String, String>();
            headers.put("Charsert", getParamsEncoding());
    //        headers.put("Content-Type", "application/json;charset=utf-8");
    //        headers.put("Accept-Encoding", "gzip,deflate");
    //        headers.put("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3");
            return headers;
        }
    

    第三步

    以上基本上就把所有的步骤给完成了,接下来就是实际的操作了,volley的好处就是可以直接在ui线程中进行操作请求返回的结果。请求网络的过程volley自动为我们开辟子线程,可以说我们不需要关心,使用方法如下:

        //建议在BaseActiviy类中初始化,并设置为protected,或者在application类中声明
        private HttpUtil httpUtil;
    
      switch (view.getId()) {
    
                case R.id.tv_getNetDataByJson: { //通过json请求
    //                Map<String, Object> params = new HashMap<>();
    //                params.put("city", "CN101010100");
    //                params.put("key", "0ae2908783b34579b5af9e8b369aae22");
    //                httpUtil.doPostByJson(BASE_URL, params, requestListener);
    
                }
                break;
                case R.id.tv_getNetDataByString: { //通过string请求
                    String location = "北京";
                    Map<String, String> params = new HashMap<>();
                    params.put("key", key);
                    params.put("location", location);
                    httpUtil.doPostByStr(BASE_URL, params, strRequestListener); //发送一个StringRequest请求
             }
                break;
    }
        /**
         * 网络请求成功回调的监听---string
         */
        private RequestListener strRequestListener = new AbsRequestListener(this) {
            @Override
            public void onSuccess(String result) {
                textViewResult.setText("String 返回的结果==" + result);
            }
        };
    
     /**
         * 网络请求成功回调的监听---json
         */
        private RequestListener requestListener = new AbsRequestListener(this) {
            @Override
            public void onSuccess(String result) {
    
                textViewResult.setText("jsonObject返回的结果==" + result);
            }
        };
    

    附上demo的链接地址volley二次封装Demo,项目实际使用

    相关文章

      网友评论

          本文标题:volley 二次封装,项目实际应用

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