码迷,mamicode.com
首页 > 移动开发 > 详细

[Android]Volley源码分析(五)

时间:2014-07-06 18:55:46      阅读:186      评论:0      收藏:0      [点我收藏+]

标签:android   des   style   blog   http   color   

前面几篇通过源码分析了Volley是怎样进行请求调度及请求是如何被实际执行的,这篇最后来看下请求结果是如何交付给请求者的(一般是Android的UI主线程)。

类图:

bubuko.com,布布扣

请求结果的交付是通过ResponseDelivery接口完成的,它有一个实现类ExecutorDelivery, 主要有postResponse()与postError()两个方法,分别在请求成功或失败时将结果提交给请求发起者。

1. 首先,在NetworkDispatcher的run()方法中,当服务器返回响应并解析完后,会调用mDelivery.postResponse(request, response);来提交请求响应。

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

2. 看ExecutorDelivery中postResponse()方法的具体实现。其中mResponsePoster是一个Executor。每post一个response,都会调用ResponseDeliveryRunnable的run()方法。在这个run()方法中,会通过mRequest.deliverResponse(mResponse.result)来传递response的result,这个result其实就是已经解析好的响应结果,比如一个表示处理结果的字符串或一个User对象。

 1 @Override
 2     public void postResponse(Request<?> request, Response<?> response) {
 3         postResponse(request, response, null);
 4     }
 5 
 6     @Override
 7     public void postResponse(Request<?> request, Response<?> response, Runnable runnable) {
 8         request.markDelivered();
 9         request.addMarker("post-response");
10         mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, runnable));
11     }
12 
13 /**
14      * A Runnable used for delivering network responses to a listener on the
15      * main thread.
16      */
17     @SuppressWarnings("rawtypes")
18     private class ResponseDeliveryRunnable implements Runnable {
19         private final Request mRequest;
20         private final Response mResponse;
21         private final Runnable mRunnable;
22 
23         public ResponseDeliveryRunnable(Request request, Response response, Runnable runnable) {
24             mRequest = request;
25             mResponse = response;
26             mRunnable = runnable;
27         }
28 
29         @SuppressWarnings("unchecked")
30         @Override
31         public void run() {
32             // If this request has canceled, finish it and don‘t deliver.
33             if (mRequest.isCanceled()) {
34                 mRequest.finish("canceled-at-delivery");
35                 return;
36             }
37 
38             // Deliver a normal response or error, depending.
39             if (mResponse.isSuccess()) {
40                 mRequest.deliverResponse(mResponse.result);
41             } else {
42                 mRequest.deliverError(mResponse.error);
43             }
44 
45             // If this is an intermediate response, add a marker, otherwise we‘re done
46             // and the request can be finished.
47             if (mResponse.intermediate) {
48                 mRequest.addMarker("intermediate-response");
49             } else {
50                 mRequest.finish("done");
51             }
52 
53             // If we have been provided a post-delivery runnable, run it.
54             if (mRunnable != null) {
55                 mRunnable.run();
56             }
57        }
58     }

3. 既然是通过Request的deliverResponse()来传递响应结果,就来看下这个方法, 第二篇中已经知道这个方法是个抽象函数,由它子类来实现。以第一篇中的MyGsonRequest为例,其实现很简单,就是调用了mListeneronResponse方法。

1 @Override
2     protected void deliverResponse(T response) {
3         mListener.onResponse(response);
4     }

这个mListener就是在主线程实例化MyGsonRequest的时候,传过来的一个Response.Listener<T>实例,这是MyGsonRequest的构造函数:

 1 public MyGsonRequest(int method
 2                         , String url                        
 3                         , Object requestBody
 4                         , Class<T> responseClass
 5                         , Listener<T> listener
 6                         , ErrorListener errorListener) {
 7         
 8         super(method, url, errorListener);
 9         this.mRequestBody = requestBody;
10         this.mResponseClass = responseClass;
11         this.mListener = listener;
12         mGson = new Gson();
13         
14     }

这里mListener也就是第一篇中在主线程中通过createRegisterSuccessListener函数返回的监听器实例,如下代码所示。  所以最终会调到这里的onResponse()方法,来做一些更新UI或提示用户请求成功之类的操作。请求失败时,响应错误结果的提交与之类似。这样,Volley就完成了响应结果的交付。

 1 private Listener<String> createRegisterSuccessListener() {
 2         return new Listener<String>() {
 3             @Override
 4             public void onResponse(String response) {
 5                 if (mProgressDialog != null) {
 6                     mProgressDialog.dismiss();
 7                 }
 8                 Toast.makeText(
 9                         RegisterActivity.this,
10                         getString(R.string.msg_register_success),
11                         Toast.LENGTH_SHORT).show();
12 
13             }
14         };
15     }

这里还有一个问题, 因为更新UI的操作只能在主线程中进行,那么ResponseDeliveryRunnable的run()方法不能再新起一个线程来执行,而应该在主线程中执行,这个是如何做到的?

其实还是用的Handler,Looper,MessageQueue的那套机制。 在Volley初始化一个RequestQueue的时候,会调用RequestQueue的如下构造函数,它构建了一个ExecutorDelivery对象,并把一个与主线程的Looper关联的一个Handler,

1 public RequestQueue(Cache cache, Network network, int threadPoolSize) {
2         this(cache, network, threadPoolSize,
3                 new ExecutorDelivery(new Handler(Looper.getMainLooper())));
4     }

然后再看下ExecutorDelivery的构造方法, 通过handler的post方法,把ResponseDeliveryRunnable 这个runnable加到了主线程的消息队列中,所以它的run()方法是在主线程中执行的。

1     public ExecutorDelivery(final Handler handler) {
2         // Make an Executor that just wraps the handler.
3         mResponsePoster = new Executor() {
4             @Override
5             public void execute(Runnable command) {
6                 handler.post(command);
7             }
8         };
9     }

 

到这里,Volley的源码基本上看完了。 还有一些诸如NetworkImageView控件(这个挺好用,直接可以取代ImageView),以及Cache的一些实现,有时间再具体看看。

 

[Android]Volley源码分析(五),布布扣,bubuko.com

[Android]Volley源码分析(五)

标签:android   des   style   blog   http   color   

原文地址:http://www.cnblogs.com/spec-dog/p/3824937.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!