高手都是这样使用volley的:创建一个带有Request对象的RequestQueue,RequestQueue为网络操作管理工作线程、从网络中读取数据并同时写入缓存中,并解析响应。请求解析原始的响应数据,volley调度已经解析的响应传递给主线程。
这篇文章主要说明的是如何高雅地使用Volley.newRequestQueue方法发送一个请求,这个方法为你创建了一个请求队列,在下一篇文章中将详细讲解。同时,还跟大家一起讨论了如何为请求队列添加一个请求和取消一个请求。
为了使用Volley库,必须在应用程序的manifest文件中添加android.perssion,INTERNET权限,否则接下来的网络连接都是扯淡了。
Volley类提供了一个非常有用的方法:Volley.newRequestQueue,能够为你创建一个请求队列(RequestQueue)。
final TextView mTextView = (TextView) findViewById(R.id.text); ... // 初始化请求队列 RequestQueue queue = Volley.newRequestQueue(this); String url ="http://www.google.com"; // 请求一个来自给定url的字符串响应 StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener() { @Override public void onResponse(String response) { // Display the first 500 characters of the response string. mTextView.setText("Response is: "+ response.substring(0,500)); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { mTextView.setText("That didn't work!"); } }); // 把期望得到的字符串请求添加进请求队列中 queue.add(stringRequest);
Volley总是在主线程中传递已经被解析的响应。为什么偏偏要在主线程中运行呢?很明显,这能够很方便地使用接受的数据填充用户界面控件,一方面使用响应处理器你可以随时修改用户界面控件,另一方面主要是这个库的设计思想,譬如关系到取消请求。
在下一篇文章中,将继续讨论如何创建一个自定义的请求队列,而不是使用Volley.newRequestQueue方法。
发送请求的操作如上面的代码段最后一行中queue.add(StringRequest),很容易理解。
用法我们已经知道了,现在跟进去看看RequestQueue类中的add方法
首先是把这个请求标记为当前队列并且同步地把它添加在当前的请求集合mCurrentRequests:
request.setRequestQueue(this); syschronized(mCurrentRequests){ mCurrentRequests.add(request); }
接着就是根据添加的先后顺序处理请求:
request.setSequence(getSequenceNumber()); request.addMarker("add-to-queue");
然后就是判断请求是否可缓存,如果不能缓存,跳过缓存队列直接连接网络:
if(!request.shouldCache()){ mNetworkQueue.add(request); return request; }
最后的那段代码是这个请求可以缓存,则同步判断该请求是否在缓存池中。
当调用add方法时,volley运行一个缓存分类线程和一个网络调度线程池。把请求添加进队列以后,缓存分类线程接收到请求并对其进行分类:如果这个请求能够在被缓存服务,已经被缓存的响应在缓存线程中被解析,同时被解析的响应被传给主线程。如果请求不能被缓存处理,则被放置在网络队列中等待数据加载。这时,第一个可用的网络线程从请求队列中拿到请求,执行HTTP事务,在工作线程中解析响应,并把响应写入缓存,同时把已经被解析的响应传给主线程。
需要明白的是,上面提到的工作线程的阻塞I/O和解析/解码都是比较耗性能的操作。你可以把请求放在任意线程中,但是响应必须在主线程中操作。以下面这张图片形象地解释请求的过程吧:
看到没有,所有的响应解析都在主线程中执行。
想要取消请求,很简单。直接调用对应请求的cancel方法即可。一旦取消请求,Volley保证你的响应处理器再也不会被调用。换句话说:在activity的opStop()方法中取消了请求队列中的请求,没必要检测getActivity()是否为null来垃圾回收响应处理器。
为了充分利用上述的优点,可跟踪正在执行的请求,以便在合适的时机取消他们。有一种很简单的方法,把每个请求绑定在一个标记对象中,使用这个标记进行取消置顶范围的请求。举个栗子吧,标记所有代表请求的activity,接着在onStop()方法中调用requestQueue.cancelAll(this)。同样,你可以标记ViewPager标签中的所有缩略图,当你优美地滑动手指切换Viewpager视图时,进行取消请求操作,这样就能避免视图都切换了但是还继续进行着网络请求导致新的Viewpager标签视图被阻塞。
下面给出一个的例子使用了字符串作为标记:
1)定义标记并把标记添加到请求中:
public static final String TAG = "MyTag"; StringRequest stringRequest; // 假设这个字符串请求存在 RequestQueue mRequestQueue; // 假设这个请求队列存在 //为字符串请求设置标记 stringRequest.setTag(TAG); //把请求添加到请求队列中 mRequestQueue.add(stringRequest);
2)在activity的onStop()方法中,把标记为“TAG”的请求取消:
@Override protected void onStop () { super.onStop(); if (mRequestQueue != null) { mRequestQueue.cancelAll(TAG); } }