Volley是由Google开发的网络请求库,该库在2013年Google I / O大会上推出的。 由于在Android SDK中缺少在不干扰用户体验的情况下进行网络请求的库,因此开发了Volley库。 在发布Volley库之前,Android程序员如果想在客户端和后台之间开发RESTFul系统,只能使用类 就算不考虑使用这两个类时出现的错误,除了简单的HTTP事务之外,所有事情都必须从头开始。 如果想缓存图像或优先处理某个请求,则那么这些都必须从头开始。 幸运的是,现在有了Volley库,专门为这些需求而量身打造。 1.为什么使用Volley?避免使用
|
1 | git clone https: //android . /platform/frameworks/volley |
直到几个星期前,您可以使用ant命令行(android update project -p .
然后 ant jar
)将所有内容包装起来,并使用简单的compile files('libs/volley.jar')
在Android Studio项目中导入JAR库 。
最近,Google已将Volley更新为Android Studio构建样式,从而难以创建独立的JAR包。 您仍然可以这样做,但只能使用旧版本的库。 我个人不鼓励你使用这个选项,尽管看起来最快。
您应该以经典的方式设置Volley ,即通过将源代码导入为module。 在Android Studio中,打开项目后,选择“ 文件”>“新建模块”,然后选择“ 导入现有项目”。 选择刚刚下载源代码的目录并确认。 名为Volley的文件夹将显示在您的项目结构中。 Android Studio自动更新您的 settings.gradle文件以包含Volley模块,因此您只需要将compile project(':volley')
添加到依赖关系即可完成。
有第三种方式。 您可以添加build.gradle文件的依赖关系部分:
1 | compile 'com.mcxiaoke.volley:library-aar:1.0.15' |
它是官方Google存储库的镜像副本,经常同步和更新。 这可能是最简单和最快速的入门方式了。 但是,请注意,这是一个非官方的 Maven存储库,不能保证,也不由Google支持。
在我看来,投入更多的时间导入官方源代码还是比较好。 这样,您可以轻松地跳转到原来的定义和实现,以便在有疑问的情况下,您可以随时依靠官方的Volley源代码,甚至可以根据需要进行更改。
Volley大多数情况下只用两个类工作, RequestQueue
和Request
。 您首先创建一个 RequestQueue
,它管理工作线程并将解析的结果传递回主线程。 然后,给RequestQueue传递一个或多个 Request
对象。
Request
构造函数总是把方法类型(GET,POST等)、资源的URL和事件侦听器作为参数。 然后,根据请求的类型,它可能会要求一些更多的变量。
在下面的例子中,我通过调用一个Volley方法 Volley.newRequestQueue
来创建一个RequestQueue
对象。 这将使用Volley定义的默认值设置RequestQueue
对象。
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | // Request a string response StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() { @Override public void onResponse(String response) { // Result handling System.out.println(response.substring( 0 , 100 )); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { // Error handling System.out.println( "Something went wrong!" ); error.printStackTrace(); } }); // Add the request to the queue Volley.newRequestQueue( this ).add(stringRequest); |
正如你所看到的,这是非常简单的。 您创建请求并将其添加到请求队列。 你完成了。
请注意,监听器的语法类似于AsyncTask.onPostExecute
,只是它变成了onResponse
。 这不是巧合。 使用Volley的开发人员有意使库的API与AsyncTask
方法类似 。 这使得从使用AsyncTask
切换到Volley更容易。
如果您必须在多个activity中进行多个请求,则应避免使用上述方法Volley.newRequestQueue.add
。 最好是实例化一个共享的请求队列,并在您的项目中使用它:
1 | MySingletonClass.getInstance().getRequestQueue().add(myRequest); |
我们将在本系列的下一个教程中专门开发这样的东西。
Volley可以实现三种非常常见的请求类型:
StringRequest
ImageRequest
JsonRequest
这些类中的每一个都继承了我们之前使用的Result
类。 我们已经在前面的例子看过StringRequest
了。 让我们来看看JsonRequest
工作原理。
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | JsonObjectRequest jsonRequest = new JsonObjectRequest (Request.Method.GET, url, null , new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { // the response is already constructed as a JSONObject! try { response = response.getJSONObject( "args" ); String site = response.getString( "site" ), network = response.getString( "network" ); System.out.println( "Site: " +site+ "\nNetwork: " +network); } catch (JSONException e) { e.printStackTrace(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { error.printStackTrace(); } }); Volley.newRequestQueue( this ).add(jsonRequest); |
美丽。 不是吗? 您可以看到,结果类型已设置为JSONObject
。 你也可以请求一个JSONArray
如果你想要,使用JsonArrayRequest
而不是一个JsonObjectRequest
进请求。
如前所述,构造函数的第一个参数是要使用的HTTP方法。 然后,您可以提供从中获取JSON的URL。 上面的例子中的第三个变量是 null
。 这很好,因为它表示没有参数将随请求一起发出。 最后,您有监听器接收JSON响应和错误响应。 如果你想忽略错误,你可以传入null
。
获取图像需要做更多的工作。 有三种请求图像的方法。 ImageRequest
是标准的。 它显示在共同的ImageView
中请求的图片,该图片通过提供的URL进行获取。 您可能希望Volley执行的所有解码和调整大小操作都发生在工作线程上。 第二个选项是 ImageLoader
类,您可以将其视为大量的编排者ImageRequests
,例如加载ListView
图像。 第三个选项是 NetworkImageView
,这是ImageView
布局项的一种XML替代。
我们来看一个例子。
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 | mImageView = (ImageView) findViewById(R.id.image); ImageRequest imgRequest = new ImageRequest(url, new Response.Listener<Bitmap>() { @Override public void onResponse(Bitmap response) { mImageView.setImageBitmap(response); } }, 0 , 0 , ImageView.ScaleType.FIT_XY, Bitmap.Config.ARGB_8888, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { mImageView.setBackgroundColor(Color.parseColor( "#ff0000" )); error.printStackTrace(); } }); Volley.newRequestQueue( this ).add(imgRequest); |
第一个参数是图片的URL,第二个参数是监听结果的监听器。 第三和第四个参数是整数maxWidth
和 maxHeight
。 您可以将它们设置0
来忽略这些参数。 之后,ImageRequest
请求ScaleType
用于计算所需的图像大小和格式来解码位图。 我建议解码格式总是使用Bitmap.Config.ARGB_8888
。 最后,我们传递监听错误的监听器。
请注意,Volley会自动将此请求的优先级设置为LOW
。
1 2 3 4 5 6 | // Snippet taken from ImageRequest.java, // in the Volley source code @Override public Priority getPriority() { return Priority.LOW; } |
从GET请求切换到POST请求很简单。 您需要更改Request.Method
请求的构造函数并重写getParams
方法,返回包含请求参数的Map<String, String> 。
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | StringRequest postRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() { @Override public void onResponse(String response) { try { JSONObject jsonResponse = new JSONObject(response).getJSONObject( "form" ); String site = jsonResponse.getString( "site" ), network = jsonResponse.getString( "network" ); System.out.println( "Site: " +site+ "\nNetwork: " +network); } catch (JSONException e) { e.printStackTrace(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { error.printStackTrace(); } } ) { @Override protected Map<String, String> getParams() { Map<String, String> params = new HashMap<>(); // the POST parameters: params.put( "site" , "code" ); params.put( "network" , "tutsplus" ); return params; } }; Volley.newRequestQueue( this ).add(postRequest); |
如果要取消所有请求,请将以下代码段添加到 onStop
方法中:
01 02 03 04 05 06 07 08 09 10 11 | @Override protected void onStop() { super .onStop(); mRequestQueue.cancelAll( new RequestQueue.RequestFilter() { @Override public boolean apply(Request<?> request) { // do I have to cancel this? return true ; // -> always yes } }); } |
这样,您就不用担心用户在onResponse
被调用时activity已经被销毁了的可能性。 因为在这种情况下会抛出NullPointerException
异常。
然而,POST和PUT请求应该继续,即使在用户更改activity之后。 我们可以通过使用标签来实现。 构建GET请求时,向其添加一个标签。
1 2 3 | // after declaring your request request.setTag( "GET" ); mRequestQueue.add(request); |
要取消所有待处理的GET请求,我们只需添加以下代码行:
1 | mRequestQueue.cancelAll( "GET" ); |
这样,您只能取消GET请求,使其他请求保持不变。 请注意,您现在必须手动处理activity过早销毁的情况。
Volley不提供设置请求的Cookie的方法,也不提供设置优先级。 这可能在将来研究,因为它是一个严重的遗漏。 但是,暂时还要继承Request
类。
对于管理cookies,您可以使用请求的标题来重写getHeaders
方法:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | public class CustomRequest extends JsonObjectRequest { // Since we're extending a Request class // we just use its constructor public CustomRequest( int method, String url, JSONObject jsonRequest, Response.Listener<JSONObject> listener, Response.ErrorListener errorListener) { super (method, url, jsonRequest, listener, errorListener); } private Map<String, String> headers = new HashMap<>(); /** * Custom class! */ public void setCookies(List<String> cookies) { StringBuilder sb = new StringBuilder(); for (String cookie : cookies) { sb.append(cookie).append( "; " ); } headers.put( "Cookie" , sb.toString()); } @Override public Map<String, String> getHeaders() throws AuthFailureError { return headers; } } |
实现后,您可以使用setCookies
直接提供请求的Cookie列表。
01 02 03 04 05 06 07 08 09 10 11 12 | // Firstly, you create the list of the cookies, // conformed to the HTTP conventions // i.e. key=value List<String> cookies = new ArrayList<>(); cookies.add( "site=code" ); cookies.add( "network=tutsplus" ); // then you invoke your custom method customRequest.setCookies(cookies); // and finally add the request to the queue Volley.newRequestQueue( this ).add(customRequest); |
对于优先级,您还需要继承Request
类,重写getPriority
方法。 实现如下:
01 02 03 04 05 06 07 08 09 10 11 12 | Priority mPriority; public void setPriority(Priority priority) { mPriority = priority; } @Override public Priority getPriority() { // If you didn't use the setPriority method, // the priority is automatically set to NORMAL return mPriority != null ? mPriority : Priority.NORMAL; } |
然后,在主线程上,调用这一行代码来设置请求的优先级:
1 | customRequest.setPriority(Priority.HIGH); |
您可以选择以下四个可能的优先级状态之一:
1 2 3 4 | Priority.LOW // images, thumbnails, ... Priority.NORMAL // residual Priority.HIGH // descriptions, lists, ... Priority.IMMEDIATE // login, logout, ... |
在本文中,我们研究了Volley网络库的工作原理。 我们首先看到了为什么使用Volley,何时使用Volley而不是已经包含在Android SDK中的另一个解决方案。 然后,我们深入了解该库的细节,查看其工作流程及其支持的请求类型。 最后,我们通过创建简单的请求并实现自定义的请求来处理cookie和优先级,从而达到我们的目的。
在本系列关于Volley的下一部分中,我们将创建一个利用Volley的简单应用程序。 我将展示如何制作火星天气应用程序,使用好奇流动站在火星上收集的天气数据。
|