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个,能够根据本身需求添加或减小。

相关文章
相关标签/搜索