Volley 源碼解讀

  你們都知道谷歌如今已經不維護volley框架,爲何如今還要分析volley源碼呢。html

     首先,volley框架的設計思想是很是值得借鑑,翻下當下我的開源 的一些網絡框架,不少都是借鑑的volley的設計思想完成的。android

     另外,volley 源碼相對簡單易懂。json

 

1、首先volley使用不一樣請求模式須要new一個相應的request對象緩存

以stringrequest爲例:網絡

 1 public void testVolley() {
 2         RequestQueue requestQueue = Volley.newRequestQueue(this);//建立一個隊列
 3         StringRequest stringRequest = new StringRequest("", new Response.Listener<String>() {
 4             @Override
 5             public void onResponse(String response) {
 6 
 7             }
 8         }, new Response.ErrorListener() {
 9             @Override
10             public void onErrorResponse(VolleyError error) {
11 
12             }
13         });
14         requestQueue.add(stringRequest);//把1請求添加進隊列
15 
16     }

同理須要json串的請求,則new出一個JsonRequest   圖片則new出  ImageRequest   這是標準的策略模式。方便擴展,好比咱們後期須要請求自定義的數據格式,就能夠繼承request這個類,比照stringrequest寫出本身的request來完成網絡數據的獲取和解析。app

具體使用代碼就不寫了。框架

2、源碼分析ide

 1   public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
 2         File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);
 3 
 4         String userAgent = "volley/0";
 5         try {
 6             String packageName = context.getPackageName();
 7             PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
 8             userAgent = packageName + "/" + info.versionCode;
 9         } catch (NameNotFoundException e) {
10         }
11 
12         if (stack == null) {
13             if (Build.VERSION.SDK_INT >= 9) {
14                 stack = new HurlStack();
15             } else {
16                 // Prior to Gingerbread, HttpUrlConnection was unreliable.
17                 // See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
18                 stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
19             }
20         }
21 
22         Network network = new BasicNetwork(stack);
23 
24         RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
25         queue.start();
26 
27         return queue;
28     }

 

一、建立一個請求隊列會調用Volley類中的 newRequestQueue方法。咱們主要看第2四、25行(標紅)建立後調用了 queue的start方法源碼分析

 1   public void start() {
 2         stop();  // Make sure any currently running dispatchers are stopped.
 3         // Create the cache dispatcher and start it.
 4         mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery);
 5         mCacheDispatcher.start();
 6 
 7         // Create network dispatchers (and corresponding threads) up to the pool size.
 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     }

二、建立一個緩存線程四、5行和四個網絡請求線程8--12行。(mDispatchers.length默認值爲4)並 調用他們的start()方法post

    CacheDispatcher和NetworkDispatcher都是繼承於 Thead類的。start的方法就是啓動該線程

三、你們都熟悉thread的用法,調用start後確定是執行run方法咱們接下來看看NetworkDispatcher的run方法作了什麼

 1  @Override
 2     public void run() {
 3         Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
 4         while (true) {
 5             long startTimeMs = SystemClock.elapsedRealtime();
 6             Request<?> request;
 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 
18             try {
19                 request.addMarker("network-queue-take");
20 
21                 // If the request was cancelled already, do not perform the
22                 // network request.
23                 if (request.isCanceled()) {
24                     request.finish("network-discard-cancelled");
25                     continue;
26                 }
27 
28                 addTrafficStatsTag(request);
29 
30                 // Perform the network request.
31                 NetworkResponse networkResponse = mNetwork.performRequest(request);
32                 request.addMarker("network-http-complete");
33 
34                 // If the server returned 304 AND we delivered a response already,
35                 // we're done -- don't deliver a second identical response.
36                 if (networkResponse.notModified && request.hasHadResponseDelivered()) {
37                     request.finish("not-modified");
38                     continue;
39                 }
40 
41                 // Parse the response here on the worker thread.
42                 Response<?> response = request.parseNetworkResponse(networkResponse);
43                 request.addMarker("network-parse-complete");
44 
45                 // Write to cache if applicable.
46                 // TODO: Only update cache metadata instead of entire record for 304s.
47                 if (request.shouldCache() && response.cacheEntry != null) {
48                     mCache.put(request.getCacheKey(), response.cacheEntry);
49                     request.addMarker("network-cache-written");
50                 }
51 
52                 // Post the response back.
53                 request.markDelivered();
54                 mDelivery.postResponse(request, response);
55             } catch (VolleyError volleyError) {
56                 volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs);
57                 parseAndDeliverNetworkError(request, volleyError);
58             } catch (Exception e) {
59                 VolleyLog.e(e, "Unhandled exception %s", e.toString());
60                 VolleyError volleyError = new VolleyError(e);
61                 volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs);
62                 mDelivery.postError(request, volleyError);
63             }
64         }
65     }

第四行是一個while(true)循環。說明該方法是一直在執行。主要邏輯是從requestQueue中不斷取出網絡任務去執行。二queue中的任務就是在咱們使用volley時的最後一行代碼 requestQueue.add(stringRequest);//把1請求添加進隊列

看到此處你們就須要明白,爲何volley官方明確要求 咱們全部的網絡請求使用同一個 requestQueue,而不是每次都new出來。   

由於new出一個requestQueue後,隊裏中會默認有5個線程在一直等待任務的加入。咱們只須要每次把新的請求  add進去便可 requestQueue.add(stringRequest);

若是每次都new出一個queue會浪費大量資源。

本篇總結:

一、new出一個隊列  requestQueue

二、new出一個合適的request

三、把request加入(add)到隊列中去執行

四、requestQueue 只建議new一次,也就是在app中,只維護一個requestqueue,以後的網絡請求都是往此隊列中添加request便可。

五、requestQueue  默認是5個線程,緩存一個,網絡請求4個,能夠根據本身需求添加或減小。

相關文章
相關標籤/搜索