我们先来Volley请求网络的代码,StringRequest为例: RequestQueue requestQueue = Volley.newRequestQueue(this); requestQueue.add(getStringRequest()); public StringRequest getStringRequest() { return new StringRequest("https://suggest.taobao.com/sug?code=utf-8&q=beizi", new Response.Listener<String>() { @Override public void onResponse(String response) { Log.e(getClass().getName(), response); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e(getClass().getName(), error.getMessage()); } } ); } public class StringRequest extends Request<String> { private Listener<String> mListener; public StringRequest(int method, String url, Listener<String> listener, ErrorListener errorListener) { super(method, url, errorListener); mListener = listener; } ... @Override protected void deliverResponse(String response) { if (mListener != null) { mListener.onResponse(response); } } @Override protected Response<String> parseNetworkResponse(NetworkResponse response) { String parsed; try { parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); } catch (UnsupportedEncodingException e) { parsed = new String(response.data); } return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response)); } } 1.RequestQueue public static RequestQueue newRequestQueue(Context context, HttpStack stack, int maxDiskCacheBytes) { File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR); String userAgent = "volley/0"; try { String packageName = context.getPackageName(); PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0); userAgent = packageName + "/" + info.versionCode; } catch (NameNotFoundException e) { } /** * 根据不同的系统版本号实例化不同的请求类,如果版本号小于9,用HttpClient * 如果版本号大于9,用HttpUrlConnection */ if (stack == null) { if (Build.VERSION.SDK_INT >= 9) { stack = new HurlStack(); } else { // Prior to Gingerbread, HttpUrlConnection was unreliable. // See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent)); } } //把实例化的stack传递进BasicNetwork,实例化Network Network network = new BasicNetwork(stack); RequestQueue queue; if (maxDiskCacheBytes <= -1){ // No maximum size specified //实例化RequestQueue类 queue = new RequestQueue(new DiskBasedCache(cacheDir), network); } else { // Disk cache size specified queue = new RequestQueue(new DiskBasedCache(cacheDir, maxDiskCacheBytes), network); } //调用RequestQueue的start()方法 queue.start(); return queue; } Queue.start源码如下: public void start() { stop(); // Make sure any currently running dispatchers are stopped. // Create the cache dispatcher and start it. mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery); mCacheDispatcher.start(); // Create network dispatchers (and corresponding threads) up to the pool size. for (int i = 0; i < mDispatchers.length; i++) { NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork, mCache, mDelivery); mDispatchers[i] = networkDispatcher; networkDispatcher.start(); } } 2.CacheDispatcher类继承自Thread,接着调用了它的start()方法,开始了一条新的缓存线程。接着是一个for循环,根据设置的mDispatchers数组大小来开启多个网络请求线程,默认是4条网络请求线程。 到目前为止,Volley.newRequestQueue()方法完成了,即我们的网络请求第一步,建立请求队列完成。建立请求队列所做的工作是,创建文件缓存(默认),实例化BasicNetwork,实例化Delivery用于发送线程请求,创建一条缓存线程和四条网络请求线程(默认)并运行。CacheDispatcher的run方法如下: @Override 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 { //获取缓存队列中的一个请求. 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 (request.isCanceled()) { request.finish("cache-discard-canceled"); continue; } // 查看是否有缓存响应 Cache.Entry entry = mCache.get(request.getCacheKey()); if (entry == null) { request.addMarker("cache-miss"); //如果缓存响应为空就加入队列 mNetworkQueue.put(request); continue; } // 判断缓存响应是否过期 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-parsed"); 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()); } } } public <T> Request<T> add(Request<T> request) { // Tag the request as belonging to this queue and add it to the set of current requests. //标记当前请求,表示这个请求由当前RequestQueue处理 request.setRequestQueue(this); synchronized (mCurrentRequests) { mCurrentRequests.add(request); } // Process requests in the order they are added. //获得当前请求的序号 request.setSequence(getSequenceNumber()); request.addMarker("add-to-queue"); // If the request is uncacheable, skip the cache queue and go straight to the network. //如果请求不能缓存,直接添加到网络请求队列,默认是可以缓存 if (!request.shouldCache()) { mNetworkQueue.add(request); return request; } // Insert request into stage if there's already a request with the same cache key in flight. // 锁定当前代码块,只能一条线程执行 synchronized (mWaitingRequests) { String cacheKey = request.getCacheKey(); //是否有相同请求正在处理 if (mWaitingRequests.containsKey(cacheKey)) { // There is already a request in flight. Queue up. //如果有相同请求正在处理,那么把这个请求放进mWaitingRequest中,等待。 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中,同时也放进mCacheQueue缓存队列中 //这代表这个请求已经开始在缓存线程中运行了 mWaitingRequests.put(cacheKey, null); mCacheQueue.add(request); } return request; } } @Override 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-parsed"); 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()); } } } 3.网络调度线程NetworkDispatcher,当缓存不存在或者过期会把请求加入到请求队列,开始工作了。 @Override 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(); } ... try { ... // Perform the network request. //调用BasicNetwork实现类进行网络请求,并获得响应 1 NetworkResponse networkResponse = mNetwork.performRequest(request); ... // Parse the response here on the worker thread. //对响应进行解析 Response<?> response = request.parseNetworkResponse(networkResponse); request.addMarker("network-parse-complete"); ... request.markDelivered(); mDelivery.postResponse(request, response); // Write to cache if applicable. //将响应结果写进缓存 if (request.shouldCache() && response.cacheEntry != null) { mCache.put(request.getCacheKey(), response.cacheEntry); request.addMarker("network-cache-written"); } } ... } } 4.BasicNetwork的performRequest方法: @Override public NetworkResponse performRequest(Request<?> request) throws VolleyError { long requestStart = SystemClock.elapsedRealtime(); while (true) { HttpResponse httpResponse = null; byte[] responseContents = null; Map<String, String> responseHeaders = Collections.emptyMap(); try { // Gather headers. Map<String, String> headers = new HashMap<String, String>(); addCacheHeaders(headers, request.getCacheEntry()); httpResponse = mHttpStack.performRequest(request, headers); // 1 StatusLine statusLine = httpResponse.getStatusLine(); int statusCode = statusLine.getStatusCode(); responseHeaders = convertHeaders(httpResponse.getAllHeaders()); // Handle cache validation. if (statusCode == HttpStatus.SC_NOT_MODIFIED) { Entry entry = request.getCacheEntry(); if (entry == null) { return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, null, responseHeaders, true, SystemClock.elapsedRealtime() - requestStart); // 2 } // A HTTP 304 response does not have all header fields. We // have to use the header fields from the cache entry plus // the new ones from the response. // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5 entry.responseHeaders.putAll(responseHeaders); return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, entry.data, entry.responseHeaders, true, SystemClock.elapsedRealtime() - requestStart); } ... } } mHttpStack.performRequest();这里调用了mHttpStack的performRequest方法,那么mHttpStack是什么呢?我们可以翻上去看看part1处实例化BasicNetwork的时候传递的stack值,该值就是根据不同的系统版本号而实例化的HttpStack对象(版本号大于9的是HurlStack,小于9的是HttpClientStack),由此可知,这里实际调用的是HurlStack.performRequest()方法,方法的内部基本是关于HttpUrlConnection的逻辑代码,这里就不展开说了。可以这么说:HurlStack封装好了HttpUrlConnection,而HttpClientStack封装了HttpClient。该方法返回了httpResponse,接着把这个响应交由处处理,封装成NetworkResponse对象并返回。在NetworkDispatcher的run()方法获取返回的NetworkResponse对象后,对响应解析. 5.ExecutorDelivery通知主线程,请看postResponse方法: @Override public void postResponse(Request<?> request, Response<?> response) { postResponse(request, response, null); } @Override public void postResponse(Request<?> request, Response<?> response, Runnable runnable) { request.markDelivered(); request.addMarker("post-response"); mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, runnable)); } 在方法内部调用了mResponsePoster的execute()方法,那么,这个mResponsePoster是在哪里来的呢?其实这个成员变量是在ExecutorDelivery实例化的时候同时实例化的,而ExecutorDelivery则是在RequestQueue实例化的时候同时实例化的,读者可以自行查看相应的构造方法,其实这些工作在par 1建立请求队列的时候已经全部做好了。 接着我们可以看以下代码,ExecutorDelivery的ExecutorDelivery方法: public ExecutorDelivery(final Handler handler) { // Make an Executor that just wraps the handler. //实例化Executor,并且重写execute方法 mResponsePoster = new Executor() { @Override public void execute(Runnable command) { //这里获取的handler是主线程的handler,可看part 1 (2) handler.post(command); } }; } execute()方法接收一个Runnable对象,那么我们回到上面的mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, runnable));可以看出这里实例化了一个ResponseDeliveryRunnable对象作为Runnable对象。而这里的ResponseDeliveryRunnable则是当前类Executor的一个内部类,实现了Runnable接口,我们来看看: @SuppressWarnings("rawtypes") private class ResponseDeliveryRunnable implements Runnable { private final Request mRequest; private final Response mResponse; private final Runnable mRunnable; //构造方法 ... @Override public void run() { // If this request has canceled, finish it and don't deliver. if (mRequest.isCanceled()) { mRequest.finish("canceled-at-delivery"); return; } // Deliver a normal response or error, depending. if (mResponse.isSuccess()) { mRequest.deliverResponse(mResponse.result); // 1 } else { mRequest.deliverError(mResponse.error); } ... } } } 在上面,①号代码回调到了Request的deliverResponse方法,即此时通知了主线程,请求已经完成,此时在Request子类重写的deliverResponse方法则会调用onResponse()方法,那么我们的Activity就能方便调用解析好的请求结果了。
Volley简单分析
最新推荐文章于 2022-02-13 12:19:44 发布