由Volley的GsonRequest引发的思考

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是你对网络拿到的数据,怎么解析成自己想要的数据形式。

相关推荐