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

 

posted @ 2022-08-09 10:06  熊猫Panda先生  阅读(465)  评论(0编辑  收藏  举报