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

来源:互联网 发布:跟踪js执行 编辑:程序博客网 时间:2024/05/18 01:03

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

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);    }

使用

 /**     * 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数,使用的时候直接拿到对象操作就行了,我们尝试下

先改一下接口

public interface OnResponseListener {    void success(Object result);    void failure(String errorMessage);}

HttpClient.java

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);    }

使用

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的过程,调用的时候强转一下对象的类型就行了

重新封装的框架的好处还有很多,可以打印每次请求和响应的数据,批量处理空值,还可以在这里进行数据缓存,包括后期的一些扩展都很方便

0 0