• Android使用Volley之JsonObjectRequest访问网络


    Volley是一个为Android开发提供更快捷更健壮更简单的网络操作框架。

    Volley非常适合去进行数据量不大、但通信频繁的网络操作,而对于大数据量的网络操作,比如说下载文件等,Volley的表现就会非常糟糕,就不适合了。

    引入

    有两种方式:

    1、下载jar包导入项目(适合离线开发)

    切换到“Project”视图,找到app/libs目录,将volley.jar复制到libs文件夹下,右键选择【Add As Library】

    2、在build.gradle中引入依赖(推荐这种方式)

    implementation 'com.android.volley:volley:1.2.1'

    步骤

    1、创建一个请求队列RequestQueue

    2、创建Request对象

    3、将请求对象添加到请求队列中

    实现

    1、AndroidManifest.xml中添加网络访问权限

    <uses-permission android:name="android.permission.INTERNET" />

    2、禁用掉明文流量请求的检查

    参见 https://www.cnblogs.com/lihuawei/p/16458853.html 中的“禁用掉明文流量请求的检查”部分。

    3、创建请求队列

    与一般的网络请求不同,Volley把所有请求都保存在一个请求队列中,然后在请求队列中按优先级一个一个取出请求,然后发送出去,因此我们先要实例化一个请求队列。

    private static RequestQueue requestQueue;
    requestQueue = Volley.newRequestQueue(getApplicationContext()); //把上下文context作为参数传递进去

    4、创建请求对象

    三种请求

    在Volley内,一般的Http请求对象有三种,分别是StringRequest,JsonObjectRequest和JsonArrayRequest。

    而每个对象都可以使用GET和POST请求方式。

    从它们的名字可以知道,

    StringRequest是请求一段字符串,

    JsonObjectRequest是请求一个JSON对象,

    JsonArrayRequest是请求一组JSON数组。

    我们从最简单的StrringRequest说起。

    (1)StringRequest

    我们先来了解一下他的构造方法,第2个构造方法就是默认GET(method=0)请求方式

    /**
     * @param method 请求的方式,可以选择GET或者POST
     *        url  请求的网址
     *        listener 请求成功的回调函数
     *        errorListener 请求失败的回调函数
     */
    public StringRequest(int method, String url, com.android.volley.Response.Listener<String> listener, com.android.volley.Response.ErrorListener errorListener) {
        super(method, url, errorListener);
        this.mLock = new Object();
        this.mListener = listener;
    }
    
    public StringRequest(String url, com.android.volley.Response.Listener<String> listener, com.android.volley.Response.ErrorListener errorListener) {
        this(0, url, listener, errorListener);
    }

    通过构造方法获取StringRequest的实例后,通过把这个实例添加进请求队列中,就能正常地进行网络通信了

    下面我们来实战一下,以大赛提供的平台获取新闻列表为例(http://218.7.112.123:10001/prod-api/press/press/list)

    public void submitString() {
        RequestQueue queue = Volley.newRequestQueue(getApplicationContext()); // 或传参MainActivity.this
        StringRequest request = new StringRequest("http://218.7.112.123:10001/prod-api/press/press/list", new com.android.volley.Response.Listener<String>() {
            @Override
            public void onResponse(String s) {
                Log.d(TAG, "onResponse: s = " + s);
            }
        }, new com.android.volley.Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                Log.d(TAG, "onErrorResponse: volleyError = " + volleyError.getMessage());
            }
        });
        queue.add(request);
    }

    运行之后,即可以得到服务器返回的字符串类型的结果,保存在onResponse(String s)方法的参数s中。

    如果我们发现s中的中文字符是乱码,是因为Volley里面默认编码为ISO-8859-1 (Latin1),不是utf-8,这时我们需要重写StringRequest的parseNetworkResponse()这个方法。

    public void submitString() {
        RequestQueue queue = Volley.newRequestQueue(getApplicationContext());
        StringRequest request = new StringRequest("http://218.7.112.123:10001/prod-api/press/press/list", new com.android.volley.Response.Listener<String>() {
            @Override
            public void onResponse(String s) {
                Log.d(TAG, "onResponse: s = " + s);
            }
        }, new com.android.volley.Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                Log.d(TAG, "onErrorResponse: volleyError = " + volleyError.getMessage());
            }
        }) {
            @Override
            protected com.android.volley.Response<String> parseNetworkResponse(NetworkResponse response) {
                String parsed = null;
                try {
                    parsed = new String(response.data, "utf-8");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                return com.android.volley.Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));
            }
        };
        queue.add(request);
    }

    (2)JsonObjectRequest和JsonArrayRequest

    以上两个类的用法和StringRequest很类似,同样有着GET和POST的请求方式。

    JsonObjectRequest 和 JsonArrayRequest有着一个共同的父类JsonRequest。

    JsonObjectRequest请求的是一个JSON对象,而JsonArrayRequest请求的是一个JSON数组,这里就以JsonObjectRequest为代表讲述。

    我们先看看构造器:

    public JsonObjectRequest(int method, String url, JSONObject jsonRequest, com.android.volley.Response.Listener<JSONObject> listener, com.android.volley.Response.ErrorListener errorListener) {
        super(method, url, jsonRequest == null ? null : jsonRequest.toString(), listener, errorListener);
    }
    
    public JsonObjectRequest(String url, JSONObject jsonRequest, com.android.volley.Response.Listener<JSONObject> listener, com.android.volley.Response.ErrorListener errorListener) {
        this(jsonRequest == null ? 0 : 1, url, jsonRequest, listener, errorListener);
    }

    从构造器可以看出,它和StringRequest的构造方法大同小异,但有一点要注意的是,JsonObjectRequest和JsonArrayRequest的构造参数有一个是JSONObject jsonRequest,这个就是Json形式的请求体。

    如果是POST请求,我们就要提前使用JSONObject的构造方法和put方法,创建一个对象,然后通过JsonObjectRequest构造器把请求体传进去,而不用像StringRequest那样通过重写父类的getParams()来写入请求参数。

    实例化了请求实例后,添加进请求队列即可。

    我们以大赛平台用户登录为例。

    public void submitJsonObject() {
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("username", "panda");
            jsonObject.put("password", "123456");
    
            RequestQueue queue = Volley.newRequestQueue(getApplicationContext()); // MainActivity.this
            JsonObjectRequest request = new JsonObjectRequest(com.android.volley.Request.Method.POST,
                    "http://218.7.112.123:10001/prod-api/api/login",
                    jsonObject,
                    new com.android.volley.Response.Listener<JSONObject>() {
                        @Override
                        public void onResponse(JSONObject jsonObject) {
                            Log.d(TAG, "onResponse: jsonObject = " + jsonObject);
                            LoginData loginData = new Gson().fromJson(jsonObject.toString(), LoginData.class);
                            Log.d(TAG, "onResponse: loginData = " + loginData.getMsg());
                            Log.d(TAG, "onResponse: loginData = " + loginData.getCode());
                            Log.d(TAG, "onResponse: loginData = " + loginData.getToken());
                        }
                    }, new com.android.volley.Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError volleyError) {
                    Log.d(TAG, "onResponse: volleyError = " + volleyError.getMessage());
                }
            });
            queue.add(request);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    其中存放登录数据的LoginData.java类的源码如下:

    public class LoginData {
        private int code;
        private String msg;
        private String token;
    
        public int getCode() {
            return code;
        }
    
        public void setCode(int code) {
            this.code = code;
        }
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    
        public String getToken() {
            return token;
        }
    
        public void setToken(String token) {
            this.token = token;
        }
    
        @Override
        public String toString() {
            return "LoginData{" +
                    "code=" + code +
                    ", msg='" + msg + '\'' +
                    ", token='" + token + '\'' +
                    '}';
        }
    }

    我们上面的例子就是使用了POST的请求方式。

    如果我们需要在请求的时候,设置请求头(Header)的话,我们可以重写getHeaders()方法。

    例如,有的请求需要安全认证的接口,需要在请求头设置认证信息, 格式如下:

    参数: Authorization

    参数值: 登录获取 TOKEN

    有的请求需要设置参数Content-Type,参数值application/json; charset=utf-8,我们都可以在重写的getHeaders()方法使用Map来设置。

    我们以大赛平台查询个人基本信息为例。

    public void submitJsonObject() {
        RequestQueue queue = Volley.newRequestQueue(getApplicationContext()); // MainActivity.this
        JsonObjectRequest request = new JsonObjectRequest("http://218.7.112.123:10001/prod-api/api/common/user/getInfo",
                null,
                new com.android.volley.Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject jsonObject) {
                        Log.d(TAG, "onResponse: jsonObject = " + jsonObject.toString());
                    }
                }, new com.android.volley.Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                Log.d(TAG, "onResponse: volleyError = " + volleyError.getMessage());
            }
        }) {
            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                Map<String, String> map = new HashMap<String, String>();
                map.put("Authorization", Constant.TOKEN);
                map.put("Content-Type", "application/json; charset=utf-8");
                return map;
            }
        };
        queue.add(request);
    }

    如果是GET请求,需要提设置请求参数,我们就需要重写

    我们以大赛平台查询电子钱包变动记录为例。

    public void balanceList() {
        RequestQueue queue = Volley.newRequestQueue(getApplicationContext());
        JsonObjectRequest request = new JsonObjectRequest(
                "http://218.7.112.123:10001/prod-api/api/common/balance/list",
                null,
                new com.android.volley.Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject jsonObject) {
                        Log.d(TAG, "onResponse: jsonObject = " + jsonObject);
                    }
                }, new com.android.volley.Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                Log.d(TAG, "onResponse: volleyError = " + volleyError.getMessage());
            }
        }) {
            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                Map<String, String> map = new HashMap<String, String>();
                map.put("Authorization", Constant.TOKEN);
                map.put("Content-Type", "application/x-www-form-urlencoded");
                return map;
            }
    
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                Map<String, String> map = new HashMap<String, String>();
                map.put("pageNum", "1");
                map.put("pageSize", "8");
                return map;
            }
        };
        queue.add(request);
    }
  • 相关阅读:
    Session_End引发的性能问题!
    可能引发性能问题的几个写法,看看你占哪一个.
    优化你的DiscuzNT3.0,让它跑起来(2)发帖回帖篇
    什么是经济学
    生产可能性边界和机会成本
    九宫格的实现(转)
    LAMP的安装和配置
    iPhone 开发过程中的一些小技术的总结(转)
    有效的利用资源边际成本与边际利益
    Dijkstra算法(注:单源最短路径的贪心算法)和数学归纳法<转>
  • 原文地址:https://www.cnblogs.com/lihuawei/p/16564960.html
Copyright © 2020-2023  润新知