In this tutorial, we’ll be discussing at length, an important networking library in our application, namely Android Volley. Android Volley library has been developed by Google. The first glimpses of it were seen in Google I/O 2013. Let’s see what it has in store!

在本教程中,我们将详细讨论应用程序中的一个重要网络库,即Android Volley。 Android Volley库由Google开发。 谷歌I / O 2013首次展示了它。让我们来看看它的功能!

Android Volley (Android Volley)

Networking is a key component in most of the Android Applications today. Using an AsyncTask might not be the best option when we have too many networking requests to handle. AsyncTask can’t prioritize parallel/multiple requests in an orderly manner. Besides they have a lot of boilerplate code. Here’s where Android Volley library comes as a handy tool. It has some powerful features and is a lot faster than AsyncTask.

网络是当今大多数Android应用程序中的关键组件。 当我们有太多网络请求需要处理时,使用AsyncTask可能不是最佳选择。 AsyncTask无法按顺序排列并行/多个请求的优先级。 此外,它们还有很多样板代码。 这是Android Volley库随手提供的工具。 它具有一些强大的功能,并且比AsyncTask快很多。

Android Volley Library的优点 (Advantages of Android Volley Library)

  1. Automatic scheduling of all network requests.

    自动调度所有网络请求。
  2. Multiple concurrent network connections.

    多个并发网络连接。
  3. Requests queuing and prioritization.

    请求排队和确定优先级。
  4. Caching responses. It supports memory and disk-based caches.

    缓存响应。 它支持基于内存和磁盘的缓存。
  5. Cancelling one or more requests.

    取消一个或多个请求。
  6. Built-in support for String, Images, JSONObject and JSONArray Requests.

    对字符串,图像,JSONObject和JSONArray请求的内置支持。
  7. Ability to create custom requests.

    能够创建自定义请求。
  8. Built-in NetworkImageView widget to load images from a URL easily.

    内置的NetworkImageView小部件可轻松从URL加载图像。
  9. Support for retrying requests.

    支持重试请求。
  10. Powerful debugging and tracing tools to catch errors.

    强大的调试和跟踪工具可捕获错误。

Android Volley入门 (Getting Started with Android Volley)

To integrate Volley in your Android Studio Project, you need to add the following dependency in your build.gradle file:

要将Volley集成到您的Android Studio项目中,您需要在build.gradle文件中添加以下依赖build.gradle

compile 'com.android.volley:volley:1.0.0'

Unlike Retrofit, which requires a bunch of libraries like OkHttp, Picasso for complete functionalities, Volley Library is much smaller in size.

与Retrofit不同,Volley Library的大小要小得多, Retrofit需要一堆类似OkHttp , Picasso的库来实现完整的功能。

Note: With the introduction of Android Studio 3.0 IDE the keyword compile is replaced by implementation in the dependencies. Both can be used interchangeably.

注意 :随着Android Studio 3.0 IDE的引入,关键字compile被依赖项中的implementation替换。 两者可以互换使用。

The Fundamental classes of Volley are listed below.

下面列出了凌空基础课程。

  • RequestQueue

    RequestQueue
  • Requests

    Requests
  • Response

    Response

Android Volley RequestQueue (Android Volley RequestQueue)

This is the basic building block of Volley. The name speaks for itself. A RequestQueue is used to queue all the requests and handle the responses. Also, it is responsible for managing the worker threads for parallel requests besides reading and writing to and from the cache. A RequestQueue works in a FIFO manner(First In First Out). At a time it can handle four requests simultaneously. A RequestQueue is instantiated in the following way in a class.

这是Volley的基本构建块。 名字足以说明问题。 RequestQueue用于将所有请求排队并处理响应。 而且,除了读写缓存外,它还负责管理并行请求的工作线程。 RequestQueue以FIFO方式(先进先出)工作。 一次它可以同时处理四个请求。 在类中以以下方式实例化RequestQueue。

RequestQueue requestQueue = Volley.newRequestQueue(this);

this refers to the context. It can be activity or application’s context. The above code initializes the RequestQueue with a default set of parameters. We can initialize the RequestQueue with our own set of parameters as shown below.

this是指上下文。 它可以是活动或应用程序的上下文。 上面的代码使用默认的一组参数初始化RequestQueue。 我们可以使用我们自己的一组参数来初始化RequestQueue,如下所示。

RequestQueue mRequestQueue;// Instantiate the cacheCache cache = new DiskBasedCache(getCacheDir(), 1024 * 1024); // 1MB cap// Set up the network to use HttpURLConnection as the HTTP client.Network network = new BasicNetwork(new HurlStack());// Instantiate the RequestQueue with the cache and network.mRequestQueue = new RequestQueue(cache, network);// Start the queuemRequestQueue.start();

We’ve initialized our own instances of Cache and Network with custom parameters.
Call the method mRequestQueue.stop() to stop the queue that’ll handle the requests.

我们已经使用自定义参数初始化了自己的Cache和Network实例。
调用方法mRequestQueue.stop()停止将处理请求的队列。

Android Volley请求 (Android Volley Request)

Request instances are built to define a network request. These are used to support GET and POST requests.
Request class acts as the base class which can be extended to define a custom request.
Volley provides the following types of Requests built-in:

构建请求实例以定义网络请求。 这些用于支持GET和POST请求。
请求类充当可扩展以定义自定义请求的基类。
排球提供以下内置的请求类型:

  • StringRequest

    字符串请求
  • JsonObjectRequest

    JsonObjectRequest
  • JsonArrayRequest

    JsonArrayRequest
  • ImageRequest

    图片请求

Android Volley StringRequest (Android Volley StringRequest)

StringRequest is used when you want the response returned in the form of a String. You can then parse the response using Gson or JSON as per your requirement.
StringRequest has two forms of constructors as shown in the image below.


We’ll discuss the first constructor here.

当您希望响应以字符串形式返回时,使用StringRequest 。 然后,您可以根据需要使用Gson或JSON解析响应。
StringRequest具有两种形式的构造函数,如下图所示。

我们将在这里讨论第一个构造函数。

StringRequest(int method, String url, Response.Listener listener, Response.ErrorListener errorListener)
  • method : Expects an argument among GET, POST, PUT, DELETE.

    方法 :需要GET,POST,PUT,DELETE之间的参数。
  • url : URl to fetch the response at.

    url :获取响应的URl。
  • listener : Listens for a success response. We need to implement and override the following method in here.
    @Override  public void onResponse(String response){  //response parameter is of the same type as defined in the constructor.   }

    监听器 :监听成功响应。 我们需要在这里实现并重写以下方法。
  • errorListener: Listens for an error response. We need to implement the following method in here.
    @Override  public void onErrorResponse(VolleyError error){  //handle your error here. We'll look at   }

    errorListener :侦听错误响应。 我们需要在这里实现以下方法。

A sample code snippet of a string request is given below.

字符串请求的示例代码段如下所示。

RequestQueue queue = Volley.newRequestQueue(this);StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener() {                @Override                public void onResponse(String response) {                    VolleyLog.wtf(response, "utf-8");                }            }, new Response.ErrorListener() {                @Override                public void onErrorResponse(VolleyError error) {                    VolleyLog.wtf(error.getMessage(), "utf-8");                }            });queue.add(stringRequest);

The response or error will be delivered to the onResponse/onErrorResponse classes that we defined in our request above.
queue.add(stringRequest); is used to add the Request to the RequestQueue.
The code snippet written above can be simplified to improve the readability.

响应或错误将传递到我们在上面的请求中定义的onResponse / onErrorResponse类。
queue.add(stringRequest); 用于将请求添加到RequestQueue
上面编写的代码段可以简化以提高可读性。

Response.ErrorListener errorListener = new Response.ErrorListener() {        @Override        public void onErrorResponse(VolleyError error) {            VolleyLog.wtf(error.getMessage(), "utf-8");        }    };    Response.Listener responseListener = new Response.Listener() {        @Override        public void onResponse(String response) {            VolleyLog.wtf(response);        }    };StringRequest stringRequest = new StringRequest(Request.Method.GET, url, responseListener, errorListener);

The constructor looks much better now.
To send parameters in request body we need to override either the getParams() or getBody() method of the request class.
Additionally, we can override the getHeaders() and the getBodyContentType() methods too to specify the headers and content type formats respectively.
getHeaders() are useful for authentication.
To override the Request Method type from the first parameter, getMethod() is implemented.
The constructor with skeleton code of the above mentioned methods is given below.

现在构造函数看起来好多了。
要在请求正文中发送参数,我们需要重写请求类的getParams()getBody()方法。
另外,我们也可以重写getHeaders()getBodyContentType()方法来分别指定标头和内容类型格式。
getHeaders()对于身份验证很有用。
要从第一个参数覆盖请求方法类型,将实现getMethod()
下面给出了具有上述方法的框架代码的构造函数。

StringRequest stringRequest = new StringRequest(Request.Method.GET, url, responseListener, errorListener){        @Override        public Map getParams() {            Map params = new HashMap();            params.put("key", "value");            return params;        }        @Override        public byte[] getBody() throws AuthFailureError {            String requestBody = "";  //The request body goes in here.            try {                return requestBody.getBytes("utf-8");            } catch (UnsupportedEncodingException e) {                e.printStackTrace();                VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", requestBody, "utf-8");                return null;            }        }        @Override        public Map getHeaders() throws AuthFailureError {            HashMap headers = new HashMap();            headers.put("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");            String credentials = "sample:JournalDev@123";            String auth = "Basic "                        + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);            headers.put("Authorization",auth); //authentication            return headers;        }        @Override        public String getBodyContentType() {            return "application/x-www-form-urlencoded; charset=utf-8";        }        @Override        public int getMethod() {             return Method.POST;        }    };

Parameters and headers are specified as a key-value pair in the getParams() and getHeaders() methods respectively.

参数和标头分别在getParams()getHeaders()方法中指定为键值对。

Note: getParams() method is ignored when the request type is a GET. So to pass parameters we’ll need to concatenate them in the URL string as shown below.

注意 :当请求类型为GET时,将忽略getParams()方法。 因此,要传递参数,我们需要将其串联在URL字符串中,如下所示。

String BASE_URL = "https://reqres.in";String url = String.format(BASE_URL + "/api/users?page=%1$s", "2");

%1$s is used for the first param. %2$s, %3$s and so on for the second, third parameters.

%1$s用于第一个参数。 第二个,第三个参数为%2$s%3$s ,依此类推。

Android Volley JsonObjectRequest (Android Volley JsonObjectRequest)

JsonObjectRequest is used to send and receive JSONObject from the server. It extends the class JsonRequest.
The two forms of constructors are given below.


We’ll look at the second constructor here.

JsonObjectRequest用于从服务器发送和接收JSONObject。 它扩展了类JsonRequest。
下面给出了两种形式的构造函数。

我们将在这里查看第二个构造函数。

JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(url, null, new Response.Listener() {        @Override        public void onResponse(JSONObject response) {                VolleyLog.wtf(response.toString());        }    }, new Response.ErrorListener() {        @Override        public void onErrorResponse(VolleyError error) {            VolleyLog.wtf(error.getMessage(), "utf-8");        }    });queue.add(jsonObjectRequest)

An optional JSONObject can be passed as the request body in the second parameter of the constructor.
We’ve set it to null for now.

可以将可选的JSONObject作为请求主体传递给构造函数的第二个参数。
我们现在将其设置为null。

JsonObjectRequest can override the same set of methods (getHeaders(), getBodyContentType(), getBody(), getMethod()) like the StringRequest except getParams().

除了getParams()之外, JsonObjectRequest可以像StringRequest一样重写相同的方法集( getHeaders()getBodyContentType()getBody()getMethod() getParams()

JsonObjectRequest is meant for passing a JSONObject with the request. Hence getParams() gets ignored.
Overriding getBody() isn’t neccessary in a JsonObjectRequest since passing a JSONObject as the second parameter does the same implicitly.

JsonObjectRequest用于将JSONObject与请求一起传递。 因此, getParams()被忽略。
在JsonObjectRequest中不需要覆盖getBody() ,因为传递JSONObject作为第二个参数会隐式地执行相同的操作。

If you eventually override getBody(), the second parameter passed in the constructor would be ignored.
Since the Request type isn’t defined in the above constructor, the request would automatically identify the method(GET,POST, PUT or DELETE) from the url. To explicitily specify the method type we can override the getMethod()

如果最终重写getBody() ,则将忽略构造函数中传递的第二个参数。
由于上述构造函数中未定义请求类型,因此请求将自动从网址中识别方法(GET,POST,PUT或DELETE)。 要明确指定方法类型,我们可以覆盖getMethod()

JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(url, null, responseListener, errorListener){        @Override        public int getMethod() {             return Method.POST; //This specifies the Method type to POST explicitly.        }        @Override        public byte[] getBody() {            //Building the response body here would ignore the JSONObject passed in the second parameter.        }    };

Android Volley JsonArrayRequest (Android Volley JsonArrayRequest)

JsonArrayRequest is used to send and retrieve JSONArray to and from the server. It extends the JsonRequest class and functions the same way as JsonObjectRequest class.
A JSONArrayRequest can’t handle a request that returns a JSONObject.
Following are the two forms of constructors.


Let’s look at the second constructor.

JsonArrayRequest用于向服务器发送和从服务器检索JSONArray。 它扩展了JsonRequest类并以与JsonObjectRequest类相同的方式起作用。
JSONArrayRequest无法处理返回JSONObject的请求。
以下是构造函数的两种形式。

让我们看一下第二个构造函数。

JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(Request.Method.POST, url, null, new Response.Listener() {        @Override        public void onResponse(JSONArray response) {                    }    }, new Response.ErrorListener() {        @Override        public void onErrorResponse(VolleyError error) {                  VolleyLog.wtf(error.getMessage(), "utf-8");                    }    });

Android Volley ImageRequest (Android Volley ImageRequest)

Using ImageRequest is the classical and standard way to fetch images from a URL. An ImageRequest returns a Bitmap Object that we can eventually display in our ImageView.
Following are the two constructors present in the class.

使用ImageRequest是从URL提取图像的经典和标准方法。 ImageRequest返回一个位图对象,该对象最终可以显示在ImageView中。
以下是该类中存在的两个构造函数。

Let’s use the second constructor since the first one now stands deprecated.
Besides the url, response and error listeners, the constructor expects the width, height, scaleType and Config values for the bitmap.

让我们使用第二个构造函数,因为第一个构造函数现在已弃用。
除了url,响应和错误侦听器之外,构造函数还需要位图的宽度,高度,scaleType和Config值。

RequestQueue queue = Volley.newRequestQueue(this);ImageRequest imageRequest = new ImageRequest(IMAGE_URL, new Response.Listener() {            @Override            public void onResponse(Bitmap response) {                if (response != null) {                    imageView.setImageBitmap(response);                }            }        }, 200, 200, ImageView.ScaleType.CENTER_CROP, Bitmap.Config.ARGB_8888, new Response.ErrorListener() {            @Override            public void onErrorResponse(VolleyError error) {                    VolleyLog.wtf(error.getMessage(), "utf-8");            }        });queue.add(imageRequest);

The RequestQueue has a RequestFinishedListener. The listener gets triggered everytime a request in the queue is finished.

RequestQueue具有一个RequestFinishedListener 。 每当队列中的请求完成时,都会触发侦听器。

queue.addRequestFinishedListener(new RequestQueue.RequestFinishedListener() {            @Override            public void onRequestFinished(Request request) {                try {                    if (request.getCacheEntry() != null) {                        String cacheValue = new String(request.getCacheEntry().data, "UTF-8");                        Log.d(TAG, request.getCacheKey() + " " + cacheValue);                    }                } catch (UnsupportedEncodingException e) {                    e.printStackTrace();                }            }        });    

Android Volley错误处理 (Android Volley Error Handling)

onErrorResponse() passes an instance of VolleyError as we have seen above.
Following are the major types of errors that can be returned in the instance.

onErrorResponse()通过如我们所看到的上述VolleyError的一个实例。
以下是实例中可以返回的主要错误类型。

  • AuthFailureError: When the authentication fails.

    AuthFailureError :身份验证失败时。
  • NetworkError: Server Error, DNS issues etc.

    NetworkError :服务器错误,DNS问题等。
  • NoConnectionError: When there is no internet connection.

    NoConnectionError :没有互联网连接时。
  • ParseError: Generally returned in a JsonObjectRequest or JsonArrayRequest when the JSON response is malformed.

    ParseError :当JSON响应格式错误时,通常在JsonObjectRequest或JsonArrayRequest中返回。
  • ServerError: The server responded with an error status code (401, 500 etc)

    ServerError :服务器以错误状态代码(401、500等)响应
  • TimeoutError: When a request timeout occurs. Volley has a default timeout of 2.5 seconds.

    TimeoutError :发生请求超时时。 排球的默认超时为2.5秒。

Android Volley取消请求 (Android Volley Cancelling Requests)

Volley has a powerful API for canceling requests. Request cancellation is important in situations where the Activity needs to be destroyed. Cancellation of requests is possible using tags.

Volley有一个强大的API用于取消请求。 在需要销毁活动的情况下,取消请求很重要。 使用标签可以取消请求。

JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(url, null, responseListener, errorListener);jsonObjectRequest.setTag("Sample");JsonObjectRequest jsonObjectRequest2 = new JsonObjectRequest(url_2, null, responseListener, errorListener);jsonObjectRequest2.setTag("No sample");queue.add(jsonObjectRequest);queue.add(jsonObjectRequest2);queue.cancelAll("Sample"); //Cancels all requests with tag "Sample" present in the RequestQueue.//Alternative way....queue.cancelAll(new RequestQueue.RequestFilter() {            @Override            public boolean apply(Request<?> request) {                return request.getTag().equals("Sample"); //requests with the condition true are cancelled.            }        });

Android Volley优先处理请求 (Android Volley Prioritizing Requests)

A priority can be set on each request present in the RequestQueue. Doing so the RequestQueue would run the requests based on the priorities instead of FIFO. A priority can be assigned by overriding the method getPriority() in the constructor. Following are the possible states:

可以为RequestQueue中存在的每个请求设置优先级。 这样做,RequestQueue将基于优先级而不是FIFO运行请求。 可以通过重写构造函数中的getPriority()方法来分配优先级。 以下是可能的状态:

  • Priority.LOW: Used to load images.

    Priority.LOW :用于加载图像。
  • Priority.NORMAL: Default value.

    Priority.NORMAL :默认值。
  • Priority.HIGH: Used to load texts.

    Priority.HIGH :用于加载文本。
  • Priority.IMMEDIATE: Used in places like login/logout.

    Priority.IMMEDIATE :用于登录/注销之类的地方。

Following code snippet assigns priority to requests.

以下代码段为请求分配优先级。

RequestQueue queue = Volley.newRequestQueue(this);Response.Listener jsonResponseListener = new Response.Listener() {        @Override        public void onResponse(JSONObject response) {        }    };    Response.Listener stringResponseListener = new Response.Listener() {        @Override        public void onResponse(String response) {        }    };    Response.Listener imageResponseListener = new Response.Listener() {        @Override        public void onResponse(Bitmap response) {        }    };    Response.ErrorListener errorListener = new Response.ErrorListener() {        @Override        public void onErrorResponse(VolleyError error) {            VolleyLog.wtf(error.getMessage(), "utf-8");        }    };StringRequest stringRequest = new StringRequest(Request.Method.GET, url, stringResponseListener, errorListener){            @Override            public Priority getPriority() {                return Priority.IMMEDIATE;            }};JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(url, null, jsonResponseListener, errorListener){            @Override            public Priority getPriority() {                return Priority.HIGH;            }};;ImageRequest imageRequest = new ImageRequest(IMAGE_URL, imageResponseListener, 200, 200, ImageView.ScaleType.CENTER_CROP, Bitmap.Config.ARGB_8888, errorListener){            @Override            public Priority getPriority() {                return Priority.LOW;            }};;queue.add(imageRequest);queue.add(jsonObjectRequest);queue.add(stringRequest);//Order of requests run : stringRequest > jsonRequest > imageRequest

Android Volley缓存 (Android Volley Caching)

Caches are enabled by default for the above mentioned Request types. The response data is typically stored in the form of byte array

默认情况下,上述请求类型会启用缓存。 响应数据通常以字节数组的形式存储

Disabling Cache

禁用缓存

stringRequest.setShouldCache(false)

Accessing the Cache

访问缓存

String cacheValue = new String(stringRequest.getCacheEntry().data, "UTF-8");//Accessing from the RequestQueueString cacheValue = new String(queue.getCache().get(url).data, "UTF-8");//The Request URL is stored in the cache key ...String url = request.getCacheKey();//Check other details in the cache.stringRequest.getCacheEntry().isExpired() //checks if the cache is expired or not.stringRequest.getCacheEntry().lastModified

Clearing cache

清除缓存

queue.getCache().remove(url); //removes cache for the specific url.//clear all cache....queue.getCache().clear();

Invalidate cache: Invalidating a cache would show the cached data until the new response is returned. That response would override the current cache.

使缓存无效 :使缓存无效将显示缓存的数据,直到返回新的响应为止。 该响应将覆盖当前的缓存。

queue.getCache().invalidate(url, true);

Android Volley ImageLoader和NetworkImageView (Android Volley ImageLoader and NetworkImageView)

We’ve used an ImageRequest to retrieve an image bitmap from the response before.
Volley provides us with NetworkImageView widget that directly loads the image from the URL. Besides, it lets us set a default placeholder as well as an error drawable.
ImageLoader is responsible for loading the images using a BitmapLruCache().

之前,我们已经使用ImageRequest从响应中检索图像位图。
Volley为我们提供了NetworkImageView小部件,该小部件可直接从URL加载图像。 此外,它还允许我们设置默认的占位符以及可绘制的错误。
ImageLoader负责使用BitmapLruCache()加载图像。

setImageFromUrl() method directly sets the image returned from the url onto the NetworkImageView instance. We need to pass the URL and ImageLoader instance in this method to fetch the image.

setImageFromUrl()方法直接将从url返回的图像设置到NetworkImageView实例上。 我们需要在此方法中传递URL和ImageLoader实例以获取图像。

networkImageView.setDefaultImageResId(R.mipmap.ic_launcher);networkImageView.setErrorImageResId(R.drawable.ic_error);ImageLoader imageLoader = new ImageLoader(mRequestQueue, new BitmapLruCache(64000)); //size is in Kb.networkImageView.setImageUrl(IMAGE_URL, imageLoader);// Loads the image with placeholder and error imageimageLoader.get(IMAGE_URL, ImageLoader.getImageListener(networkImageView, R.mipmap.ic_launcher, R.drawable.ic_error));

Note: To troubleshoot and log debug traces set the following line in your code.

注意:要排除故障并记录调试跟踪,请在代码中设置以下行。

VolleyLog.DEBUG = true;

We can create our own Custom Requests too by extending Request. The two abstract methods parseNetworkResponse() and deliverResponse() need to be overriden.
This brings an end to this comprehensive tutorial on Volley. We’ll implement Volley in an application using the above-learned concepts in our next tutorial.

我们也可以通过扩展Request 来创建自己的自定义请求。 需要重写两个抽象方法parseNetworkResponse()deliverResponse()
这样就结束了有关Volley的综合教程。 在下一个教程中,我们将使用上述知识在应用程序中实现Volley。

Reference: GitHub Page, API Doc

参考: GitHub Page , API Doc

翻译自: https://www.journaldev.com/17126/android-volley

更多相关文章

  1. 安卓布局应用学习代码附带效果图
  2. WebRTC-M68-官方编译文档-Android'
  3. 【Android动画九章】-帧动画
  4. LocationManager定位
  5. Application
  6. kotlin超简单recyclerView测试
  7. MediaProvider源码分析
  8. Android-生命周期方法
  9. android ndk Toolchain

随机推荐

  1. Android小疑问解答:为什么ScrollView嵌套
  2. Android(安卓)Studio、Eclipse ADT无法更
  3. Android调用C# .net 的WebService接口
  4. Android中“android:elevation”设置阴影
  5. android的计算器简单布局————网格布
  6. Android(安卓)N之后 Webview导致多语言切
  7. Android(安卓)文字自动滚动(跑马灯)效果的
  8. 【Android(安卓)Studio】android 自测工
  9. Android之B面试题③Context 上下文 你必
  10. 【定制Android系统】Android(安卓)7.1 默