软件编程
位置:首页>> 软件编程>> Android编程>> 解析Android框架之Volley源码

解析Android框架之Volley源码

作者:handsome黄  发布时间:2021-09-30 19:44:28 

标签:Android,Volley

Volley简单使用

我这里是以依赖架包的形式 ,大家也可以以gradle的形式进行依赖。

解析Android框架之Volley源码

好了,接下来上代码了.....


//获取volley的请求对象
       RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
       StringRequest stringRequest = new StringRequest(StringRequest.Method.GET, "http://www.baidu.com", new Response.Listener<String>() {
           @Override
           public void onResponse(String s) {
               Log.d("MainActivity", "----->" + s);

}
       }, new Response.ErrorListener() {
           @Override
           public void onErrorResponse(VolleyError volleyError) {
               Log.d("MainActivity", "---volleyError-->" + volleyError);
           }
       });
       requestQueue.add(stringRequest);

从代码可以看出,首先newRequestQueue来获取到一个请求队列,然后在将StringRequest这个请求添加到请求队列中,就可以了,就是这么简单。当然请求不值StringRequest,还有JsonObjectRequest ,ImageRequest等等但是用法都是一样的,这里就不贴代码了。Volley的简单使用就这样可以进行请求了。是不是很简单

Volley执行原理

但是这个不是本篇的重点,重点是分析一下这些是怎么执行的。先上一张图

解析Android框架之Volley源码

我们先看看newRequestQueue这个内部是怎么执行的,代码一开始连续执行了几个重载方法,最后走到newRequestQueue


public static RequestQueue newRequestQueue(Context context, HttpStack stack, int maxDiskCacheBytes) {
   File cacheDir = new File(context.getCacheDir(), "volley");
   String userAgent = "volley/0";

try {
       String packageName = context.getPackageName();
       PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
       userAgent = packageName + "/" + info.versionCode;
   } catch (NameNotFoundException var7) {
       ;
   }

//这里进行了一个版本的判断 2.3之前用的是HTTPClient,2.3之后使用的是HttpURLConnection
   if (stack == null) {
       if (VERSION.SDK_INT >= 9) {
           stack = new HurlStack();
       } else {
           stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
       }
   }

Network network = new BasicNetwork((HttpStack)stack);
   RequestQueue queue;
   if (maxDiskCacheBytes <= -1) {
       queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
   } else {
       queue = new RequestQueue(new DiskBasedCache(cacheDir, maxDiskCacheBytes), network);
   }

queue.start();
   return queue;
}

在这里,我们看到了一个版本判断,是不是瞬间感觉有点熟悉,没错,我们前面说的,volley2.3之前用的是HTTPClient,2.3之后使用的是HttpURLConnection就是在这里进行判断的。接着看queue.start();


public void start() {
       this.stop();
       this.mCacheDispatcher = new CacheDispatcher(this.mCacheQueue, this.mNetworkQueue, this.mCache, this.mDelivery);
       this.mCacheDispatcher.start();

for(int i = 0; i < this.mDispatchers.length; ++i) {
           NetworkDispatcher networkDispatcher = new NetworkDispatcher(this.mNetworkQueue, this.mNetwork, this.mCache, this.mDelivery);
           this.mDispatchers[i] = networkDispatcher;
           networkDispatcher.start();
       }

}

mCacheDispatcher是缓存调度线程,NetworkDispatcher是网络调度线程,而这个this.mDispatchers.length系统默认的大小为4,也就是说,在这里总共启动了5个线程在后台运行。

好了,到这里,就可以了,看源码不要每一行都弄懂,不然,出不来了。到这里就拿到了这个RequestQueue对象。回过头来看前面使用的代码


//获取volley的请求对象
RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
StringRequest stringRequest = new StringRequest(StringRequest.Method.GET, "http://www.baidu.com", new Response.Listener<String>() {
   @Override
   public void onResponse(String s) {
       Log.d("MainActivity", "----->" + s);

}
}, new Response.ErrorListener() {
   @Override
   public void onErrorResponse(VolleyError volleyError) {
       Log.d("MainActivity", "---volleyError-->" + volleyError);
   }
});
requestQueue.add(stringRequest);

我们拿到这个RequestQueue对象以后,然后就把这个请求通过add方法添加到队列中,我们看看这个add()方法是怎么执行的。


public <T> Request<T> add(Request<T> request) {
       request.setRequestQueue(this);
       Set var2 = this.mCurrentRequests;
       synchronized(this.mCurrentRequests) {
           this.mCurrentRequests.add(request);
       }

request.setSequence(this.getSequenceNumber());
       request.addMarker("add-to-queue");
       if (!request.shouldCache()) { //如果不能缓存
           this.mNetworkQueue.add(request);
           return request;
       } else {
           Map var7 = this.mWaitingRequests;
           synchronized(this.mWaitingRequests) {
               String cacheKey = request.getCacheKey();
               if (this.mWaitingRequests.containsKey(cacheKey)) { //判断之前是否执行过,但是还没有返回结果
                   Queue<Request<?>> stagedRequests = (Queue)this.mWaitingRequests.get(cacheKey);
                   if (stagedRequests == null) {
                       stagedRequests = new LinkedList();
                   }

((Queue)stagedRequests).add(request);
                   this.mWaitingRequests.put(cacheKey, stagedRequests);
                   if (VolleyLog.DEBUG) {
                       VolleyLog.v("Request for cacheKey=%s is in flight, putting on hold.", new Object[]{cacheKey});
                   }
               } else {
               //没有的话就将请求加入缓存队列mCacheQueue,同时加入mWaitingRequests中用来做下次同样请求来时的重复判断依据
                   this.mWaitingRequests.put(cacheKey, (Object)null);
                   this.mCacheQueue.add(request);
               }

return request;
           }
       }
   }

从代码中可以看出,首先判断是否可以缓存,当然,默认是可以缓存的。如果不能缓存的话,则通过this.mNetworkQueue.add(request);将请求添加到网络请求队列中。如果可以缓存,则还会判断一次这个请求是否请求,如果执行过就就通过this.mWaitingRequests.put(cacheKey, stagedRequests);添加到mWaitingRequests队列,不在重复请求。否则就加入到缓存队列。

大体的流程是这样。现在我们看看缓存的,和网络的是怎么执行的。我们找到start()方法


public void start() {
       this.stop();
       this.mCacheDispatcher = new CacheDispatcher(this.mCacheQueue, this.mNetworkQueue, this.mCache, this.mDelivery);
       this.mCacheDispatcher.start();

for(int i = 0; i < this.mDispatchers.length; ++i) {
           NetworkDispatcher networkDispatcher = new NetworkDispatcher(this.mNetworkQueue, this.mNetwork, this.mCache, this.mDelivery);
           this.mDispatchers[i] = networkDispatcher;
           networkDispatcher.start();
       }

}

先看CacheDispatcher,找到run()方法


public void run() {
       if (DEBUG) {
           VolleyLog.v("start new dispatcher", new Object[0]);
       }

Process.setThreadPriority(10);
       this.mCache.initialize();

while(true) {
           while(true) {
               while(true) {
                   while(true) {
                       try {
                           while(true) {
                               final Request<?> request = (Request)this.mCacheQueue.take(); //从缓存队列中获取到一个请求
                               request.addMarker("cache-queue-take");
                               if (request.isCanceled()) { //判断请求是否取消,如果取消了,那就将该请求finish掉
                                   request.finish("cache-discard-canceled");
                               } else {
                                   Entry entry = this.mCache.get(request.getCacheKey());
                                   if (entry == null) {//如果从缓存中取出来的内容为空,则将请求加入到网络线程中再次请求
                                       request.addMarker("cache-miss");
                                       this.mNetworkQueue.put(request);
                                   } else if (entry.isExpired()) { //如果请求过期了,则将请求加入到网络线程中再次请求
                                       request.addMarker("cache-hit-expired");
                                       request.setCacheEntry(entry);
                                       this.mNetworkQueue.put(request);
                                   } else { //将数据回调到主线程
                                       request.addMarker("cache-hit");
                                       Response<?> response = request.parseNetworkResponse(new NetworkResponse(entry.data, entry.responseHeaders));
                                       request.addMarker("cache-hit-parsed");
                                       if (entry.refreshNeeded()) {
                                           request.addMarker("cache-hit-refresh-needed");
                                           request.setCacheEntry(entry);
                                           response.intermediate = true;
                                           this.mDelivery.postResponse(request, response, new Runnable() {
                                               public void run() {
                                                   try {
                                                       CacheDispatcher.this.mNetworkQueue.put(request);
                                                   } catch (InterruptedException var2) {
                                                       ;
                                                   }

}
                                           });
                                       } else {
                                           this.mDelivery.postResponse(request, response);
                                       }
                                   }
                               }
                           }
                       } catch (InterruptedException var4) {
                           if (this.mQuit) {
                               return;
                           }
                       }
                   }
               }
           }
       }
   }

这里嵌套了几个循环,有点凌乱啊,但是慢慢分析的话,就会发现,其实很清晰。我在注释上面写了,这里就不重复了

我们在看看NetworkDispatcher,看看网络线程是怎么执行的。一样找到run()方法


public void run() {
       Process.setThreadPriority(10);

while(true) {
           long startTimeMs;
           Request request;
           while(true) {
               startTimeMs = SystemClock.elapsedRealtime();

try {
                   request = (Request)this.mQueue.take(); //获取到一个请求
                   break;
               } catch (InterruptedException var6) {
                   if (this.mQuit) {
                       return;
                   }
               }
           }

try {
               request.addMarker("network-queue-take");
               if (request.isCanceled()) { //如果请求取消了,则将请求finish掉
                   request.finish("network-discard-cancelled");
               } else {//进行网络请求
                   this.addTrafficStatsTag(request);
                   NetworkResponse networkResponse = this.mNetwork.performRequest(request);
                   request.addMarker("network-http-complete");
                   if (networkResponse.notModified && request.hasHadResponseDelivered()) {
                       request.finish("not-modified");
                   } else {
                       Response<?> response = request.parseNetworkResponse(networkResponse);
                       request.addMarker("network-parse-complete");
                       if (request.shouldCache() && response.cacheEntry != null) {
                           this.mCache.put(request.getCacheKey(), response.cacheEntry);
                           request.addMarker("network-cache-written");
                       }

request.markDelivered();
                       this.mDelivery.postResponse(request, response);
                   }
               }
           } catch (VolleyError var7) {
               var7.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs);
               this.parseAndDeliverNetworkError(request, var7);
           } catch (Exception var8) {
               VolleyLog.e(var8, "Unhandled exception %s", new Object[]{var8.toString()});
               VolleyError volleyError = new VolleyError(var8);
               volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs);
               this.mDelivery.postError(request, volleyError);
           }
       }
   }

代码比较多,我们直接找到NetworkResponse networkResponse = this.mNetwork.performRequest(request);这句代码,这句代码就是请求网络的代码,最核心的。performRequest是一个接口,我们看看这个performRequest()方法。Network在最开始说版本判断的时候里面有一句代码Network network = new BasicNetwork((HttpStack)stack);  从这句代码,我们可以知道BasicNetwork才是最终实现网络请求的类,我们找到performRequest方法


public NetworkResponse performRequest(Request<?> request) throws VolleyError {
       long requestStart = SystemClock.elapsedRealtime();

while(true) {
           HttpResponse httpResponse = null;
           byte[] responseContents = null;
           Map responseHeaders = Collections.emptyMap();

try {
               Map<String, String> headers = new HashMap();
               this.addCacheHeaders(headers, request.getCacheEntry());
               httpResponse = this.mHttpStack.performRequest(request, headers);
               StatusLine statusLine = httpResponse.getStatusLine();
               int statusCode = statusLine.getStatusCode();
               responseHeaders = convertHeaders(httpResponse.getAllHeaders());
               if (statusCode == 304) {
                   Entry entry = request.getCacheEntry();
                   if (entry == null) {
                       return new NetworkResponse(304, (byte[])null, responseHeaders, true, SystemClock.elapsedRealtime() - requestStart);
                   }

entry.responseHeaders.putAll(responseHeaders);
                   return new NetworkResponse(304, entry.data, entry.responseHeaders, true, SystemClock.elapsedRealtime() - requestStart);
               }

if (statusCode == 301 || statusCode == 302) {
                   String newUrl = (String)responseHeaders.get("Location");
                   request.setRedirectUrl(newUrl);
               }

byte[] responseContents;
               if (httpResponse.getEntity() != null) {
                   responseContents = this.entityToBytes(httpResponse.getEntity());
               } else {
                   responseContents = new byte[0];
               }

long requestLifetime = SystemClock.elapsedRealtime() - requestStart;
               this.logSlowRequests(requestLifetime, request, responseContents, statusLine);
               if (statusCode >= 200 && statusCode <= 299) {
                   return new NetworkResponse(statusCode, responseContents, responseHeaders, false, SystemClock.elapsedRealtime() - requestStart);
               }

throw new IOException();
           } catch (SocketTimeoutException var12) {
               attemptRetryOnException("socket", request, new TimeoutError());
           } catch (ConnectTimeoutException var13) {
               attemptRetryOnException("connection", request, new TimeoutError());
           } catch (MalformedURLException var14) {
               throw new RuntimeException("Bad URL " + request.getUrl(), var14);
           } catch (IOException var15) {
               int statusCode = false;
               NetworkResponse networkResponse = null;
               if (httpResponse == null) {
                   throw new NoConnectionError(var15);
               }

int statusCode = httpResponse.getStatusLine().getStatusCode();
               if (statusCode != 301 && statusCode != 302) {
                   VolleyLog.e("Unexpected response code %d for %s", new Object[]{statusCode, request.getUrl()});
               } else {
                   VolleyLog.e("Request at %s has been redirected to %s", new Object[]{request.getOriginUrl(), request.getUrl()});
               }

if (responseContents == null) {
                   throw new NetworkError(networkResponse);
               }

networkResponse = new NetworkResponse(statusCode, (byte[])responseContents, responseHeaders, false, SystemClock.elapsedRealtime() - requestStart);
               if (statusCode != 401 && statusCode != 403) {
                   if (statusCode != 301 && statusCode != 302) {
                       throw new ServerError(networkResponse);
                   }

attemptRetryOnException("redirect", request, new AuthFailureError(networkResponse));
               } else {
                   attemptRetryOnException("auth", request, new AuthFailureError(networkResponse));
               }
           }
       }
   }

代码比较多,但是大多数代码是判断状态返回码的,不需要理会。

我们直接看httpResponse = this.mHttpStack.performRequest(request, headers);这一句代码,HttpStack这个有没有很熟悉。没有??没关系我在复制一次代码


if (stack == null) {
   if (VERSION.SDK_INT >= 9) {
       stack = new HurlStack();
   } else {
       stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
   }
}

还是在这个版本判断这里,这里就是HurlStack就是真正的网络请求的类了,网络请求,就是写在这个类里面的。好了,volley整个流程大概就是这样了。现在大家回过头看最初的哪一张图,是不是明了很多。

来源:https://www.cnblogs.com/huangjialin/p/9337801.html

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com