[关闭]
@yudesong 2018-02-12T03:09:19.000000Z 字数 6403 阅读 618

Volley 源码解析

volley


Volley架构图

屏幕快照 2018-01-28 22.41.50.png

Volley 的简单用法大致如下
  1. RequestQueue requestQueue = Volley.newRequestQueue(this);
  2. String url = "http://www.google.com";
  3. StringRequest stringquest = new StringRequest(Request.Method.GET,
  4. url, new Response.Listener<String>()
  5. {
  6. @Override
  7. public void onResponse(String s) {
  8. re = s;
  9. callback.onSuccess(re);
  10. }
  11. }, new Response.ErrorListener()
  12. {
  13. @Override
  14. public void onErrorResponse(VolleyError volleyError) {
  15. mNotices.setText(volleyError.getMessage());
  16. }
  17. });
  18. requestQueue.add(stringquest);

下面,通过Volley源码来简单了解一下其内部结构吧。
屏幕快照 2018-01-28 19.01.51.png

【1】首先来看看Volley这类。

  1. public class Volley {
  2. private static final String DEFAULT_CACHE_DIR = "volley";
  3. public static RequestQueue newRequestQueue(Context context) {
  4. return newRequestQueue(context, null);
  5. }
  6. public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
  7. //缓存文件
  8. File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);
  9. String userAgent = "volley/0";
  10. try {
  11. String packageName = context.getPackageName();
  12. PackageInfo info = context.getPackageManager()
  13. .getPackageInfo(packageName, 0);
  14. userAgent = packageName + "/" + info.versionCode;
  15. } catch (NameNotFoundException e) {
  16. }
  17. //策略模式
  18. if (stack == null) {
  19. if (Build.VERSION.SDK_INT >= 9) {
  20. stack = new HurlStack();
  21. } else {
  22. stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
  23. }
  24. }
  25. Network network = new BasicNetwork(stack);
  26. RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
  27. queue.start();
  28. return queue;
  29. }
  30. }

【2】RequestQueue

屏幕快照 2018-01-28 19.09.13.png

  1. public class RequestQueue {
  2. public void start() {
  3. stop(); // Make sure any currently running dispatchers are stopped.
  4. // 创建一个缓存调度线程并使之运行
  5. mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery);
  6. mCacheDispatcher.start();
  7. // 默认创建4个网络调度线程并运行
  8. for (int i = 0; i < mDispatchers.length; i++) {
  9. NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,
  10. mCache, mDelivery);
  11. mDispatchers[i] = networkDispatcher;
  12. networkDispatcher.start();
  13. }
  14. }
  15. public <T> Request<T> add(Request<T> request) {
  16. // Tag the request as belonging to this queue and add it to the set of current requests.
  17. request.setRequestQueue(this);
  18. synchronized (mCurrentRequests) {
  19. mCurrentRequests.add(request);
  20. }
  21. // Process requests in the order they are added.
  22. request.setSequence(getSequenceNumber());
  23. request.addMarker("add-to-queue");
  24. // If the request is uncacheable, skip the cache queue and go straight to the network.
  25. if (!request.shouldCache()) {
  26. mNetworkQueue.add(request);
  27. return request;
  28. }
  29. //之前是否有执行相同的请求且还没有返回结果的,如果有的话将此请求加入mWaitingRequests队列,不再重复请求
  30. synchronized (mWaitingRequests) {
  31. String cacheKey = request.getCacheKey();
  32. if (mWaitingRequests.containsKey(cacheKey)) {
  33. // There is already a request in flight. Queue up.
  34. Queue<Request<?>> stagedRequests = mWaitingRequests.get(cacheKey);
  35. if (stagedRequests == null) {
  36. stagedRequests = new LinkedList<Request<?>>();
  37. }
  38. stagedRequests.add(request);
  39. mWaitingRequests.put(cacheKey, stagedRequests);
  40. if (VolleyLog.DEBUG) {
  41. VolleyLog.v("Request for cacheKey=%s is in flight, putting on hold.", cacheKey);
  42. }
  43. } else {
  44. //没有的话就将请求加入缓存队列mCacheQueue,同时加入mWaitingRequests中用来做下次同样请求来时的重复判断依据
  45. mWaitingRequests.put(cacheKey, null);
  46. mCacheQueue.add(request);
  47. }
  48. return request;
  49. }
  50. }
  51. }

【3】CacheDispatcher 缓存调度线程

  1. public class CacheDispatcher extends Thread {
  2. @Override
  3. public void run() {
  4. if (DEBUG) VolleyLog.v("start new dispatcher");
  5. Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
  6. // Make a blocking call to initialize the cache.
  7. mCache.initialize();
  8. while (true) {
  9. try {
  10. // Get a request from the cache triage queue, blocking until
  11. // at least one is available.
  12. final Request<?> request = mCacheQueue.take();
  13. request.addMarker("cache-queue-take");
  14. // If the request has been canceled, don't bother dispatching it.
  15. if (request.isCanceled()) {
  16. request.finish("cache-discard-canceled");
  17. continue;
  18. }
  19. // Attempt to retrieve this item from cache.
  20. Cache.Entry entry = mCache.get(request.getCacheKey());
  21. if (entry == null) {
  22. request.addMarker("cache-miss");
  23. // Cache miss; send off to the network dispatcher.
  24. mNetworkQueue.put(request);
  25. continue;
  26. }
  27. // If it is completely expired, just send it to the network.
  28. if (entry.isExpired()) {
  29. request.addMarker("cache-hit-expired");
  30. request.setCacheEntry(entry);
  31. mNetworkQueue.put(request);
  32. continue;
  33. }
  34. // We have a cache hit; parse its data for delivery back to the request.
  35. request.addMarker("cache-hit");
  36. Response<?> response = request.parseNetworkResponse(
  37. new NetworkResponse(entry.data, entry.responseHeaders));
  38. request.addMarker("cache-hit-parsed");
  39. if (!entry.refreshNeeded()) {
  40. // Completely unexpired cache hit. Just deliver the response.
  41. mDelivery.postResponse(request, response);
  42. } else {
  43. // Soft-expired cache hit. We can deliver the cached response,
  44. // but we need to also send the request to the network for
  45. // refreshing.
  46. request.addMarker("cache-hit-refresh-needed");
  47. request.setCacheEntry(entry);
  48. // Mark the response as intermediate.
  49. response.intermediate = true;
  50. // Post the intermediate response back to the user and have
  51. // the delivery then forward the request along to the network.
  52. mDelivery.postResponse(request, response, new Runnable() {
  53. @Override
  54. public void run() {
  55. try {
  56. mNetworkQueue.put(request);
  57. } catch (InterruptedException e) {
  58. // Not much we can do about this.
  59. }
  60. }
  61. });
  62. }
  63. } catch (InterruptedException e) {
  64. // We may have been interrupted because it was time to quit.
  65. if (mQuit) {
  66. return;
  67. }
  68. continue;
  69. }
  70. }
  71. }
  72. }

【4】NetworkDispatcher网络调度线程

  1. public class NetworkDispatcher extends Thread {
  2. @Override
  3. public void run() {
  4. Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
  5. Request<?> request;
  6. while (true) {
  7. try {
  8. // Take a request from the queue.
  9. request = mQueue.take();
  10. } catch (InterruptedException e) {
  11. // We may have been interrupted because it was time to quit.
  12. if (mQuit) {
  13. return;
  14. }
  15. continue;
  16. }
  17. try {
  18. request.addMarker("network-queue-take");
  19. // If the request was cancelled already, do not perform the
  20. // network request.
  21. if (request.isCanceled()) {
  22. request.finish("network-discard-cancelled");
  23. continue;
  24. }
  25. addTrafficStatsTag(request);
  26. // Perform the network request.
  27. NetworkResponse networkResponse = mNetwork
  28. .performRequest(request);
  29. request.addMarker("network-http-complete");
  30. // If the server returned 304 AND we delivered a response
  31. // already,
  32. // we're done -- don't deliver a second identical response.
  33. if (networkResponse.notModified
  34. && request.hasHadResponseDelivered()) {
  35. request.finish("not-modified");
  36. continue;
  37. }
  38. // Parse the response here on the worker thread.
  39. Response<?> response = request
  40. .parseNetworkResponse(networkResponse);
  41. request.addMarker("network-parse-complete");
  42. // Write to cache if applicable.
  43. // TODO: Only update cache metadata instead of entire record for
  44. // 304s.
  45. if (request.shouldCache() && response.cacheEntry != null) {
  46. mCache.put(request.getCacheKey(), response.cacheEntry);
  47. request.addMarker("network-cache-written");
  48. }
  49. // Post the response back.
  50. request.markDelivered();
  51. mDelivery.postResponse(request, response);
  52. } catch (VolleyError volleyError) {
  53. parseAndDeliverNetworkError(request, volleyError);
  54. } catch (Exception e) {
  55. VolleyLog.e(e, "Unhandled exception %s", e.toString());
  56. mDelivery.postError(request, new VolleyError(e));
  57. }
  58. }
  59. }
  60. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注