技术水平有限,文章中所描述的错误,请帮助指出。多谢。
简单的讲,提供了如下主要的功能:
1、封装了的异步的RESTful 请求API;
2、一个优雅和稳健的请求队列;
3、一个可扩展的架构,它使开发人员能够实现自定义的请求和响应处理机制;
4、能够使用外部HTTP Client库;
5、缓存策略;
6、自定义的网络图像加载视图(NetworkImageView,ImageLoader等);
7、Volley可以绑定Content的生命周期,例如当Activity销毁时,Volley可以取消响应的网络请求。
StringRequest
这个类可以用来从服务器获取String,如果想自己解析请求响应可以使用这个类,例如返回xml数据。它还可以使用重载的构造函数定制请求。
- final String URL = "/volley/resource/recent.xml";
- StringRequest req = new StringRequest(URL, new Response.Listener
() { - @Override
- public void onResponse(String response) {
- VolleyLog.v("Response:%n %s", response);
- }
- }, new Response.ErrorListener() {
- @Override
- public void onErrorResponse(VolleyError error) {
- VolleyLog.e("Error: ", error.getMessage());
- }
- });
- // add the request object to the queue to be executed
- ApplicationController.getInstance().addToRequestQueue(req);
在添加请求的时候首先创建一个网络请求队列RequestQueue,这应该是核心的请求队列。
Volley只是一个Helper类,帮助创建RequestQueue,
*/ public RequestQueue getRequestQueue() { // lazy initialize the request queue, the queue instance will be // created when it is accessed for the first time if (mRequestQueue == null) { mRequestQueue = Volley.newRequestQueue(getApplicationContext()); } return mRequestQueue; }
newRequestQueue的具体实现代码:
// 在2.3之前的版本,建议使用apache的HttpClient来处理网络请求,在2.3之后的版本建议使用HttpUrlConnection
// 请参考:http://blog.csdn.net/forever_crying/article/details/7021174
public static RequestQueue newRequestQueue(Context context, HttpStack stack) { File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR); String userAgent = "volley/0"; try { String packageName = context.getPackageName(); PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0); userAgent = packageName + "/" + info.versionCode; } catch (NameNotFoundException e) { } if (stack == null) { if (Build.VERSION.SDK_INT >= 9) { stack = new HurlStack(); } else { // 在2.3之前的版本,建议使用apache的HttpClient来处理网络请求,在2.3之后的版本建议使用HttpUrlConnection // 请参考:http://blog.csdn.net/forever_crying/article/details/7021174 // Prior to Gingerbread, HttpUrlConnection was unreliable. // See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent)); } } Network network = new BasicNetwork(stack); RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network); queue.start(); return queue; }
Vooley初始化流程:
画了一个初始化的UML图,没学过UML,随便画画,另外求UML的学习书籍,真心不会画啊。。
大概是:Volley.newRequestQueue(),初始化网络请求队列,然后add()消息到RequestQueue,NetworkDispatcher分发消息到NetWork调用HttpStack请求网络,提交本地缓存信息到请求头,NetWork封装HttpStack返回数据,判断是否使用缓存,或者抛出相关的异常。
相关注释:
1、Volley是一个Helper类,主要负责创建出请求队列,并且启动队列消息的循环。
2、HttpStack负责解析网络请求,performRequest返回一个Apache的HttpResponse,确保返回的Response有StatusLine
注:在2.3之前的版本,建议使用apache的HttpClient来处理网络请求,在2.3之后的版本建议使用HttpUrlConnection
http://blog.csdn.net/forever_crying/article/details/7021174HurlStack,使用HttpUrlConnection,解析网络请求;HttpClientStack使用HttpClient解析网络请求
3、Network封装了HttpStack的网络请求,performRequest方法直接返回一个NetworkResponse,处理了请求异常抛出VolleyError。
4、NetworkDispatcher网络调度(线程池),分发网络请求到NetWork。
/** * RequestQueue.start() 启动缓存调度和网络调度 */ public void start() { stop(); // Make sure any currently running dispatchers are stopped. // Create the cache dispatcher and start it. mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery); mCacheDispatcher.start(); // Create network dispatchers (and corresponding threads) up to the pool size. for (int i = 0; i < mDispatchers.length; i++) { NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork, mCache, mDelivery); mDispatchers[i] = networkDispatcher; networkDispatcher.start(); } }
//BaseNetWork的主要代码 添加了一些注释
@Override public NetworkResponse performRequest(Request> request) throws VolleyError { long requestStart = SystemClock.elapsedRealtime(); while (true) { HttpResponse httpResponse = null; byte[] responseContents = null; Map
responseHeaders = new HashMap (); try { // Gather headers. Map headers = new HashMap ();//请求头信息。 addCacheHeaders(headers, request.getCacheEntry());//添加本地缓存头信息 httpResponse = mHttpStack.performRequest(request, headers);//发出网络请求 StatusLine statusLine = httpResponse.getStatusLine(); int statusCode = statusLine.getStatusCode();//HTTP状态码 responseHeaders = convertHeaders(httpResponse.getAllHeaders());//解析头信息 // Handle cache validation. if (statusCode == HttpStatus.SC_NOT_MODIFIED) {//可以使用缓存数据 return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, request.getCacheEntry().data, responseHeaders, true); } // Some responses such as 204s do not have content. We must check. if (httpResponse.getEntity() != null) {//将返回数据 转化为byte数据 responseContents = entityToBytes(httpResponse.getEntity()); } else {//如果没有返回内容。 // Add 0 byte response as a way of honestly representing a // no-content request. responseContents = new byte[0]; } // if the request is slow, log it. long requestLifetime = SystemClock.elapsedRealtime() - requestStart; //如果请求时间过长 则打印Log logSlowRequests(requestLifetime, request, responseContents, statusLine); if (statusCode < 200 || statusCode > 299) {//服务器返回异常 则抛出IOException throw new IOException(); } return new NetworkResponse(statusCode, responseContents, responseHeaders, false); } catch (SocketTimeoutException e) {//链接超时 尝试重新链接 如果达到尝试次数 则会抛出VolleyError异常,此次请求则结束。 attemptRetryOnException("socket", request, new TimeoutError()); } catch (ConnectTimeoutException e) {//链接超时 尝试重新链接 如果达到尝试次数 则会抛出VolleyError异常,此次请求则结束。 attemptRetryOnException("connection", request, new TimeoutError()); } catch (MalformedURLException e) {//Bad URL throw new RuntimeException("Bad URL " + request.getUrl(), e); } catch (IOException e) { int statusCode = 0; NetworkResponse networkResponse = null; if (httpResponse != null) { statusCode = httpResponse.getStatusLine().getStatusCode(); } else {//{//如果没有返回httpResponse,就说明没连接 throw new NoConnectionError(e); } VolleyLog.e("Unexpected response code %d for %s", statusCode, request.getUrl()); if (responseContents != null) { networkResponse = new NetworkResponse(statusCode, responseContents, responseHeaders, false); if (statusCode == HttpStatus.SC_UNAUTHORIZED || statusCode == HttpStatus.SC_FORBIDDEN) {//认证失败异常,重试 attemptRetryOnException("auth", request, new AuthFailureError(networkResponse)); } else {//服务器异常 // TODO: Only throw ServerError for 5xx status codes. throw new ServerError(networkResponse); } } else {//网络异常 throw new NetworkError(networkResponse); } } } }