您的位置:首页 > 理论基础 > 计算机网络

Android 网络请求框架总结(二)

2015-08-04 23:08 507 查看
上一篇Android 网络请求框架总结(一)总结了一些我在Android网络请求解析这一块的一些经验,过程是循序渐进的,从无到有,从不完善到完善,这一篇将继续优化以上的代码,看看还有哪些需要做的,地址,参数,回调,网络判断,请求状态判断,json解析,错误信息收集都有了,看似没有什么问题,还是结合实际的问题来分析,在很早的一个项目中我发现了一个问题,而且是在网络状态很差,我快速切换页面的时候才会出现,症状大概是这样,进去一个页面,发出了网络请求,我耐心的等待数据的加载完成,再出去另一个页面去请求另一个数据,根本就加载不出来,退出应用出去再进就好了,当时的网络请求框架是当时公司的技术总监写的,我大概看了下源码,就简单的封装了一个异步任务(AsyncTask),发现了请求是不能取消的,那就意味着当页面销毁的时候请求并没有取消,才导致的我上面描述的bug,继续优化代码

[code]public class HttpClient {
    public static RequestQueue queue = Volley.newRequestQueue(App.getContext());

    public static final String RESULT_CODE = "code"; //状态码,后台返回成功或者失败
    public static final String RETURN_MESSAGE = "message";//消息,后台返回的文本消息,提示或者错误信息
    public static final String RESULT = "result";//成功的返回结果
    public static final String SUCCESS = "1"; //成功
    public static final String FAILURE = "0";//失败

    public static void postRequest(Context context, String url, final Map<String, String> map, final OnResponseListener listener) {
        StringRequest request = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                try {
                    JSONObject jsonObject = new JSONObject(response);//将json数据转化为json对象
                    if (!jsonObject.isNull(RESULT_CODE)) {//判断code字段是否存在
                        String code = jsonObject.getString(RESULT_CODE);//活得code的值
                        if (code.equals(SUCCESS)) { //成功则继续往下判断
                            if (!jsonObject.isNull(RESULT)) {
                                String result = jsonObject.getString(RESULT);
                                listener.success(result);
                            }

                        } else if (code.equals(FAILURE)) {//失败返回错误信息
                            if (!jsonObject.isNull(RETURN_MESSAGE)) {//判断message字段是否存在
                                listener.failure(jsonObject.getString(RETURN_MESSAGE));//返回后台失败信息
                            }

                        } else {
                            listener.failure("无效的状态码");//返回状态码无效的错误信息
                        }

                    } else {
                        listener.failure("状态码不存在");//返回状态码不存在的错误信息
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                    listener.failure(e.getLocalizedMessage());//返回json异常的错误信息
                }
                listener.success(response);
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                listener.failure(error.getLocalizedMessage());//返回Volley异常的错误信息
            }
        }) {
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                return map;
            }
        };

        //判断网络是否连接
        if (NetworkUtils.isConnectedByState(App.getContext())) {
            addRequest(request, context);//将请求添加到队列
        } else {
            listener.failure("网络未连接");//返回网络未连接的错误信息
        }
    }

    /**
     * 添加请求到请求队列中
     *
     * @param request 请求
     * @param tag     目标对象,Activity或者Fragment
     */
    private static void addRequest(Request<?> request, Object tag) {
        if (tag != null) {
            request.setTag(tag);
        }
        queue.add(request);
    }

    /**
     * 取消目标对象中的所有请求
     *
     * @param tag 目标对象,Activity或者Fragment
     */
    public static void cancelRequest(Object tag) {
        queue.cancelAll(tag);
    }


使用

[code] /**
     * Activity销毁的时候取消该Activity的所有请求
     */
    @Override
    protected void onDestroy() {
        super.onDestroy();
        HttpClient.cancelRequest(this);
    }

 /**
     * Fragment 视图销毁的时候取消该Fragment的所有网络请求
     */
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        HttpClient.cancelRequest(this);
    }

 Map<String,String> map = new HashMap<>();
        map.put("key1","value1");
        map.put("key2", "value1");
    HttpClient.postRequest(this,"http://www.baidu.com", map, new OnResponseListener() {
            @Override
            public void success(String result) {
                System.out.println("result = " + result);
                //这里我新建了一个测试的对象,采用了gson来将json数据转换为bean对象
                //解析成对象,嵌套的对象也是可以的
                TestBean testBean = new Gson().fromJson(result, TestBean.class);
                //解析成list
                Type type = new TypeToken<ArrayList<TestBean>>() {
                }.getType();
                List<TestBean> testBeans = new Gson().fromJson(result, type);
                //解析成数组
                TestBean[] testBeans1 = new Gson().fromJson(result, TestBean[].class);
                //这个时候想转化为list可以调用下面的方法

                List<TestBean> testBeans2 = Arrays.asList(testBeans1);

            }

            @Override
            public void failure(String errorMessage) {
                System.out.println("errorMessage = " + errorMessage);
            }
        });


继续走,看看这个框架还可以做哪些事情,上一篇讲了关于gson解析相关的内容,注释比较详细,应该可以满足基本的需求,问题就是每次都要手动解析,使用起来还是显得有些麻烦,可以在框架中自动解析Json数,使用的时候直接拿到对象操作就行了,我们尝试下

先改一下接口

[code]public interface OnResponseListener {
    void success(Object result);

    void failure(String errorMessage);
}


HttpClient.java

[code]public class HttpClient {
    public static RequestQueue queue = Volley.newRequestQueue(App.getContext());

    public static final String RESULT_CODE = "code"; //状态码,后台返回成功或者失败
    public static final String RETURN_MESSAGE = "message";//消息,后台返回的文本消息,提示或者错误信息
    public static final String RESULT = "result";//成功的返回结果
    public static final String SUCCESS = "1"; //成功
    public static final String FAILURE = "0";//失败

    public static void postRequest(Context context, String url, final Class clazz, final Map<String, String> map, final OnResponseListener listener) {
        StringRequest request = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                try {
                    JSONObject jsonObject = new JSONObject(response);//将json数据转化为json对象
                    if (!jsonObject.isNull(RESULT_CODE)) {//判断code字段是否存在
                        String code = jsonObject.getString(RESULT_CODE);//活得code的值
                        if (code.equals(SUCCESS)) { //成功则继续往下判断
                            if (!jsonObject.isNull(RESULT)) {
                                String result = jsonObject.getString(RESULT);
                                Object o;
                                if (result.charAt(0) == '{') {
                                    //解析对象
                                    o = new Gson().fromJson(result, clazz);
                                } else {
                                    //这个方法是在stackoverflow中找到的可将json转换为list,普通的通过type去解析是不行的
                                    o = new Gson().fromJson(result, com.google.gson.internal.$Gson$Types.newParameterizedTypeWithOwner(null, ArrayList.class, clazz));
                                }
                                listener.success(o);
                            }

                        } else if (code.equals(FAILURE)) {//失败返回错误信息
                            if (!jsonObject.isNull(RETURN_MESSAGE)) {//判断message字段是否存在
                                listener.failure(jsonObject.getString(RETURN_MESSAGE));//返回后台失败信息
                            }

                        } else {
                            listener.failure("无效的状态码");//返回状态码无效的错误信息
                        }

                    } else {
                        listener.failure("状态码不存在");//返回状态码不存在的错误信息
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                    listener.failure(e.getLocalizedMessage());//返回json异常的错误信息
                }
                listener.success(response);
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                listener.failure(error.getLocalizedMessage());//返回Volley异常的错误信息
            }
        }) {
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                return map;
            }
        };

        //判断网络是否连接
        if (NetworkUtils.isConnectedByState(App.getContext())) {
            addRequest(request, context);//将请求添加到队列
        } else {
            listener.failure("网络未连接");//返回网络未连接的错误信息
        }
    }

    /**
     * 添加请求到请求队列中
     *
     * @param request 请求
     * @param tag     目标对象,Activity或者Fragment
     */
    private static void addRequest(Request<?> request, Object tag) {
        if (tag != null) {
            request.setTag(tag);
        }
        queue.add(request);
    }

    /**
     * 取消目标对象中的所有请求,在Activity或者Fragment销毁的时候调用
     *
     * @param tag 目标对象,Activity或者Fragment
     */
    public static void cancelRequest(Object tag) {
        queue.cancelAll(tag);
    }


使用

[code]HttpClient.postRequest(this, "http://www.baidu.com", TestBean.class, map, new OnResponseListener() {
            @Override
            public void success(Object result) {
                //如果result为对象
                TestBean testBean = ((TestBean) result);
                //如果result为list
                List<TestBean> testBeans = (ArrayList<TestBean>) result;
            }

            @Override
            public void failure(String errorMessage) {
                System.out.println("errorMessage = " + errorMessage);
            }
        });


这样就完成了自动解析json的过程,调用的时候强转一下对象的类型就行了

重新封装的框架的好处还有很多,可以打印每次请求和响应的数据,批量处理空值,还可以在这里进行数据缓存,包括后期的一些扩展都很方便
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: