Garment 2019-06-21
1.为什么我们在发起请求的时候,只需要往队列中插入一个request就可以了?
答:因为我们在创建requestQueue的时候,会调用Volley.newRequestQueue(Context context, HttpStack stack)方法:
public static RequestQueue newRequestQueue(Context context, HttpStack stack) { ... Network network = new BasicNetwork(stack); RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network); queue.start(); return queue; }
其中会调用RequestQueue的start方法,现在我们来看看RequestQueue的start方法:
public void start() { ... for (int i = 0; i < mDispatchers.length; i++) { NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,mCache, mDelivery); mDispatchers[i] = networkDispatcher; networkDispatcher.start(); } }
NetworkDispatcher是一个线程,里面在run方法,会有一个循环,一直取mNetworkQueue,mNetworkQueue是一个BlockQueue,通过take进行取值,取到了,然后执行mNetwork.performRequest(request):
2.parseNetWorkResponse在什么时候调用的?
答:
@Override public void run() { ... // Perform the network request. NetworkResponse networkResponse = mNetwork.performRequest(request); ... Response<?> response = request.parseNetworkResponse(networkResponse); request.addMarker("network-parse-complete"); ... request.markDelivered(); mDelivery.postResponse(request, response); ... }
NetWorkDispatcher的run方法,在执行完mNetwork.performRequest方法,即BasicNetWork的performRequest方法,拿到netWorkResponse,会调用request.parseNetworkResponse(networkResponse);所以我们在继承request的时候,重写parseNetworkResponse(networkResponse)方法,就能对网络请求的数据进行自定义的解析转换。
3.在工作线程执行完网络请求,怎么对回调在主线程,让主线程对解析后的数据进行业务处理?
从上面的代码我们可以看到,在解析完数据之后,我们会执行postResponse,这里的mDelivery对应的是ExecutorDelivery类的实例,我们可以看ExecutorDelivery的postResponse(request, response)方法:
@Override public void postResponse(Request<?> request, Response<?> response, Runnable runnable) { request.markDelivered(); request.addMarker("post-response"); mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, runnable)); }
在postResponse(request, response)方法中会调用mResponsePoster的execute方法,我们现在来看下它的方法的实现:
public ExecutorDelivery(final Handler handler) { // Make an Executor that just wraps the handler. mResponsePoster = new Executor() { @Override public void execute(Runnable command) { handler.post(command); } }; }
的execute方法,本质上是执行了Handler的post(Runnable)方法,然而我们在创建requestQueue的时候,我们实例ExecutorDelivery对象的时候,传的handler对应的looper是主线程的sMainLooper,那通过post的执行的任务我们是会执行将runnable封装成message发到主线程的messageQueue当中,然后主线程的Looper去取message来执行。(如果对handler中传递sMainLooper,然后执行就在主线程的原因,可以看下https://segmentfault.com/a/11...)
4.在主线程中执行message,怎么通过接口的形式将数据response中的泛型对象,传递给业务层?
答:我们可以看到上面发送请求的时候,我们会封装一个ResponseDeliveryRunnable,通过handle.post(runnable),我们会执行ResponseDeliveryRunnable的run方法:
public void run() { ... if (mResponse.isSuccess()) { mRequest.deliverResponse(mResponse.result); } else { mRequest.deliverError(mResponse.error); } ... }
所以,我们在集成Request的时候,需要重写deliverResponse(T response),这里就是底层访问完数据,将数据传给业务方,这个方法是主线程执行的。
总结:经过上面的分析,我相信大家应该在用volley的时候,为什么需要实现deliverResponse和parseNetworkResponse方法应该明白了吧,deliverResponse就是用来将网络获取的数据传递给业务方,parseNetworkResponse是你对网络拿到的数据,怎么解析成自己想要的数据形式。