结合开发文档分析volley(一)
2016-07-23 19:13
330 查看
首先,结合开发文档的第一篇 Sending a Simple Request来分析vollry。
http://wear.techbrood.com/training/volley/simple.html
1.添加网络权限
android.permission.INTERNET
2.newRequestQueue的使用
RequestQueue管理网络操作和读写缓冲的工作线程和解析结果。
3.传送Request
首先创建Request,以StringRequest为例。
传送Request
在创建了RequestQueue的实例对象后,后台就跑着两个线程—–one cache processing thread and a pool of network dispatch threads(一个缓冲线程和一个网络线程池).当你把request对象加到队列后,它首先被缓冲线程执行,如果request能在保存的缓冲中得到处理,那么就将缓冲的结果传送回主线程,如果request没能在缓冲中得到处理,它将会放置在网络作业队列中,然后网络线程池对其进行处理,最后,将response写入缓冲,然后把简析的response传送回主线程。
上面文字描述的图示。
然后,接下来用源码解释图示。
这是add的核心代码。它主要是先判断有没有一个和add函数的传入的request一样的request,如果有,把它加入stagedRequests 等待处理,打印出“这个request正在被执行”的log。如果没有,那么就将这个request加入mCacheQueue,交给缓冲线程去执行。这也验证了,前面说过的:add后,先把request交给缓冲线程执行,如果缓冲线程没有执行,在交给网络线程池执行。
一直在说缓冲线程和网络线程,来看一看它们的代码实现。缓冲线程的类名是CacheDispatcher,网络线程的类名是NetworkDispatcher。接下来在依次看它们的run方法。
CacheDispatcher的run方法体:结合前面说过的缓冲线程处理request的步骤来看源码,看是不是这样的。
NetworkDispatcher的run方法体:结合前面说过的网络线程处理request的步骤来看源码,看是不是这样的。
4.取消Request
可以调用cancel函数取消request。
它就是重置了一个标志位。这个标志位在哪发挥作用?
①在NetworkDispatcher的run方法体中,在执行访问网络操作之前。
② 在传送解析了的networkResponse时。(前面说到的简析response也是指简析networkResponse)
这个可以用在瀑布流解决图片乱序问题,之后会写一个小程序来用cancel解决乱序问题。
http://wear.techbrood.com/training/volley/simple.html
1.添加网络权限
android.permission.INTERNET
2.newRequestQueue的使用
RequestQueue管理网络操作和读写缓冲的工作线程和解析结果。
RequestQueue queue = Volley.newRequestQueue(this);
3.传送Request
首先创建Request,以StringRequest为例。
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!"); } });
传送Request
queue.add(stringRequest);
在创建了RequestQueue的实例对象后,后台就跑着两个线程—–one cache processing thread and a pool of network dispatch threads(一个缓冲线程和一个网络线程池).当你把request对象加到队列后,它首先被缓冲线程执行,如果request能在保存的缓冲中得到处理,那么就将缓冲的结果传送回主线程,如果request没能在缓冲中得到处理,它将会放置在网络作业队列中,然后网络线程池对其进行处理,最后,将response写入缓冲,然后把简析的response传送回主线程。
上面文字描述的图示。
然后,接下来用源码解释图示。
synchronized (mWaitingRequests) { String cacheKey = request.getCacheKey(); if (mWaitingRequests.containsKey(cacheKey)) { // There is already a request in flight. Queue up. Queue<Request<?>> stagedRequests = mWaitingRequests.get(cacheKey); if (stagedRequests == null) { stagedRequests = new LinkedList<Request<?>>(); } stagedRequests.add(request); mWaitingRequests.put(cacheKey, stagedRequests); if (VolleyLog.DEBUG) { VolleyLog.v("Request for cacheKey=%s is in flight, putting on hold.", cacheKey); } } else { // Insert 'null' queue for this cacheKey, indicating there is now a request in // flight. mWaitingRequests.put(cacheKey, null); mCacheQueue.add(request); } return request;
这是add的核心代码。它主要是先判断有没有一个和add函数的传入的request一样的request,如果有,把它加入stagedRequests 等待处理,打印出“这个request正在被执行”的log。如果没有,那么就将这个request加入mCacheQueue,交给缓冲线程去执行。这也验证了,前面说过的:add后,先把request交给缓冲线程执行,如果缓冲线程没有执行,在交给网络线程池执行。
一直在说缓冲线程和网络线程,来看一看它们的代码实现。缓冲线程的类名是CacheDispatcher,网络线程的类名是NetworkDispatcher。接下来在依次看它们的run方法。
CacheDispatcher的run方法体:结合前面说过的缓冲线程处理request的步骤来看源码,看是不是这样的。
public void run() { if (DEBUG) VolleyLog.v("start new dispatcher"); Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); // Make a blocking call to initialize the cache. mCache.initialize(); Request<?> request; while (true) { // release previous request object to avoid leaking request object when mQueue is drained. request = null; try { // Take a request from the queue. request = mCacheQueue.take(); } catch (InterruptedException e) { // We may have been interrupted because it was time to quit. if (mQuit) { return; } continue; } try { request.addMarker("cache-queue-take"); // If the request has been canceled, don't bother dispatching it. if (request.isCanceled()) { request.finish("cache-discard-canceled"); continue; } // Attempt to retrieve this item from cache. Cache.Entry entry = mCache.get(request.getCacheKey()); if (entry == null) { request.addMarker("cache-miss"); // Cache miss; send off to the network dispatcher. mNetworkQueue.put(request); continue; } // If it is completely expired, just send it to the network. if (entry.isExpired()) { request.addMarker("cache-hit-expired"); request.setCacheEntry(entry); mNetworkQueue.put(request); continue; } // We have a cache hit; parse its data for delivery back to the request. request.addMarker("cache-hit"); Response<?> response = request.parseNetworkResponse( new NetworkResponse(entry.data, entry.responseHeaders)); request.addMarker("cache-hit-pars 4000 ed"); if (!entry.refreshNeeded()) { // Completely unexpired cache hit. Just deliver the response. mDelivery.postResponse(request, response); } else { // Soft-expired cache hit. We can deliver the cached response, // but we need to also send the request to the network for // refreshing. request.addMarker("cache-hit-refresh-needed"); request.setCacheEntry(entry); // Mark the response as intermediate. response.intermediate = true; // Post the intermediate response back to the user and have // the delivery then forward the request along to the network. final Request<?> finalRequest = request; mDelivery.postResponse(request, response, new Runnable() { @Override public void run() { try { mNetworkQueue.put(finalRequest); } catch (InterruptedException e) { // Not much we can do about this. } } }); } } catch (Exception e) { VolleyLog.e(e, "Unhandled exception %s", e.toString()); } } }
NetworkDispatcher的run方法体:结合前面说过的网络线程处理request的步骤来看源码,看是不是这样的。
public void run() { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); Request<?> request; while (true) { long startTimeMs = SystemClock.elapsedRealtime(); // release previous request object to avoid leaking request object when mQueue is drained. request = null; try { // Take a request from the queue. request = mQueue.take(); } catch (InterruptedException e) { // We may have been interrupted because it was time to quit. if (mQuit) { return; } continue; } try { request.addMarker("network-queue-take"); // If the request was cancelled already, do not perform the // network request. if (request.isCanceled()) { request.finish("network-discard-cancelled"); continue; } addTrafficStatsTag(request); // Perform the network request. NetworkResponse networkResponse = mNetwork.performRequest(request); request.addMarker("network-http-complete"); // If the server returned 304 AND we delivered a response already, // we're done -- don't deliver a second identical response. if (networkResponse.notModified && request.hasHadResponseDelivered()) { request.finish("not-modified"); continue; } // Parse the response here on the worker thread. Response<?> response = request.parseNetworkResponse(networkResponse); request.addMarker("network-parse-complete"); // Write to cache if applicable. // TODO: Only update cache metadata instead of entire record for 304s. if (request.shouldCache() && response.cacheEntry != null) { mCache.put(request.getCacheKey(), response.cacheEntry); request.addMarker("network-cache-written"); } // Post the response back. request.markDelivered(); mDelivery.postResponse(request, response); } catch (VolleyError volleyError) { volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs); parseAndDeliverNetworkError(request, volleyError); } catch (Exception e) { VolleyLog.e(e, "Unhandled exception %s", e.toString()); VolleyError volleyError = new VolleyError(e); volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs); mDelivery.postError(request, volleyError); } } }
4.取消Request
可以调用cancel函数取消request。
public void cancel() { mCanceled = true; }
它就是重置了一个标志位。这个标志位在哪发挥作用?
①在NetworkDispatcher的run方法体中,在执行访问网络操作之前。
if (request.isCanceled()) { request.finish("network-discard-cancelled"); continue; }
② 在传送解析了的networkResponse时。(前面说到的简析response也是指简析networkResponse)
if (mRequest.isCanceled()) { mRequest.finish("canceled-at-delivery"); return; }
这个可以用在瀑布流解决图片乱序问题,之后会写一个小程序来用cancel解决乱序问题。
相关文章推荐
- 深入剖析Android的Volley库中的图片加载功能
- Android的HTTP类库Volley入门学习教程
- Android开发中使用Volley库发送HTTP请求的实例教程
- Android的HTTP操作库Volley的基本使用教程
- Android Volley框架使用源码分享
- 深入解读Android的Volley库的功能结构
- Netroid:强大、快速、易用、可扩展基于Volley实现的Android Http库
- Android Volley运用
- Volley学习笔记(一)
- Volley学习笔记(二)
- Android Volley完全解析(一),初识Volley的基本用法
- Android Volley完全解析(二),使用Volley加载网络图片
- Android Volley完全解析(三),定制自己的Request
- Android Volley完全解析(四),带你从源码的角度理解Volley
- android listview 异步加载图片并防止错位
- Android 网络通信框架Volley简介
- Volley的unit test
- android快速开发开源项目android-common-utils
- Volley的应用(通过Json与服务器交互)
- Android Volley解析,初识Volley的基本用法