专栏名称: 安卓开发精选
伯乐在线旗下账号,分享安卓应用相关内容,包括:安卓应用开发、设计和动态等。
目录
相关文章推荐
51好读  ›  专栏  ›  安卓开发精选

Android 网络编程(4): 从源码解析Volley(下)

安卓开发精选  · 公众号  · android  · 2016-08-21 08:50

正文

(点击上方公众号,可快速关注)


来源:刘望舒   

链接:blog.csdn.net/itachi85/article/details/51104301


接上文


   } catch (InterruptedException var4) {

                            if(this.mQuit) {

                                return;

                            }

                        }

                    }

                }

            }

        }

    }


 static {

        DEBUG = VolleyLog.DEBUG;

    }


看到四个while循环有些晕吧,让我们挑重点的说,首先从缓存队列取出请求,判断是否请求是否被取消了,如果没有则判断该请求是否有缓存的响应,如果有并且没有过期则对缓存响应进行解析并回调给主线程。接下来看看网络调度线程。


4.NetworkDispatcher网络调度线程


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()) {

                    request.finish("network-discard-cancelled");

                } else {

                    this.addTrafficStatsTag(request);

                    //请求网络

                    NetworkResponse e = this.mNetwork.performRequest(request);

                    request.addMarker("network-http-complete");

                    if(e.notModified && request.hasHadResponseDelivered()) {

                        request.finish("not-modified");

                    } else {

                        Response volleyError1 = request.parseNetworkResponse(e);

                        request.addMarker("network-parse-complete");

                        if(request.shouldCache() && volleyError1.cacheEntry != null) {                        

                            //将响应结果存入缓存

                            this.mCache.put(request.getCacheKey(), volleyError1.cacheEntry);

                            request.addMarker("network-cache-written");

                        }

 

                        request.markDelivered();

                        this.mDelivery.postResponse(request, volleyError1);

                    }

                }

            } 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);

            }

        }

    }


网络调度线程也是从队列中取出请求并且判断是否被取消了,如果没取消就去请求网络得到响应并回调给主线程。请求网络时调用this.mNetwork.performRequest(request),这个mNetwork是一个接口,实现它的类是BasicNetwork,我们来看看BasicNetwork的performRequest()方法:


public NetworkResponse performRequest(Request?> request) throws VolleyError {

        long requestStart = SystemClock.elapsedRealtime();

 

        while(true) {

            HttpResponse httpResponse = null;

            Object responseContents = null;

            Map responseHeaders = Collections.emptyMap();

 

            try {

                HashMap e = new HashMap();

                this.addCacheHeaders(e, request.getCacheEntry());

                httpResponse = this.mHttpStack.performRequest(request, e);

                StatusLine statusCode1 = httpResponse.getStatusLine();

                int networkResponse1 = statusCode1.getStatusCode();

                responseHeaders = convertHeaders(httpResponse.getAllHeaders());

                if(networkResponse1 == 304) {

                    Entry requestLifetime2 = request.getCacheEntry();

                    if(requestLifetime2 == null) {

                        return new NetworkResponse(304, (byte[])null, responseHeaders, true, SystemClock.elapsedRealtime() - requestStart);

                    }

 

                    requestLifetime2.responseHeaders.putAll(responseHeaders);

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

                }

 

 

...省略


从上面可以看到在12行调用的是HttpStack的performRequest()方法请求网络,接下来根据不同的响应状态码来返回不同的NetworkResponse。另外HttpStack也是一个接口,实现它的两个类我们在前面已经提到了就是HurlStack和HttpClientStack。让我们再回到NetworkDispatcher,请求网络后,会将响应结果存在缓存中,如果响应结果成功则调用this.mDelivery.postResponse(request, volleyError1)来回调给主线程。来看看Delivery的postResponse()方法:


public void postResponse(Request> request, Response> response, Runnable runnable) {

        request.markDelivered();

        request.addMarker("post-response");

        this.mResponsePoster.execute(new ExecutorDelivery.ResponseDeliveryRunnable(request, response, runnable));

    }


来看看ResponseDeliveryRunnable里面做了什么:


private class ResponseDeliveryRunnable implements Runnable {

        private final Request mRequest;

        private final Response mResponse;

        private final Runnable mRunnable;

 

        public ResponseDeliveryRunnable(Request request, Response response, Runnable runnable) {

            this.mRequest = request;

            this.mResponse = response;

            this.mRunnable = runnable;

        }

 

        public void run() {

            if(this.mRequest.isCanceled()) {

                this.mRequest.finish("canceled-at-delivery");

            } else {

                if(this.mResponse.isSuccess()) {

                    this.mRequest.deliverResponse(this.mResponse.result);

                } else {

                    this.mRequest.deliverError(this.mResponse.error);

                }

 

                if(this.mResponse.intermediate) {

                    this.mRequest.addMarker("intermediate-response");

                } else {

                    this.mRequest.finish("done");

                }

 

                if(this.mRunnable != null) {

                    this.mRunnable.run();

                }

 

            }

        }

    }


第17行调用了this.mRequest.deliverResponse(this.mResponse.result),这个就是实现Request抽象类必须要实现的方法,我们来看看StringRequest的源码:


public class StringRequest extends Request {

    private final Listener mListener;

 

    public StringRequest(int method, String url, Listener listener, ErrorListener errorListener) {

        super(method, url, errorListener);

        this.mListener = listener;

    }

 

    public StringRequest(String url, Listener listener, ErrorListener errorListener) {

        this(0, url, listener, errorListener);

    }

 

    protected void deliverResponse(String response) {

        this.mListener.onResponse(response);

    }

 

...省略

}


在deliverResponse方法中调用了this.mListener.onResponse(response),最终将response回调给了Response.Listener的onResponse()方法。我们用StringRequest请求网络的写法是这样的:


RequestQueue mQueue = Volley.newRequestQueue(getApplicationContext());

        StringRequest mStringRequest = new StringRequest(Request.Method.GET, "http://www.baidu.com",

                new Response.Listener() {

                    @Override

                    public void onResponse(String response) {

                        Log.i("wangshu", response);

                    }

                }, new Response.ErrorListener() {

            @Override

            public void onErrorResponse(VolleyError error) {

                Log.e("wangshu", error.getMessage(), error);

            }

        });

        //将请求添加在请求队列中

        mQueue.add(mStringRequest);


看到第5行整个Volley的大致流程都通了吧,好了关于Volley的源码就讲到这里。


------------- 推荐 ------------


范品社推出的极客T恤,含程序员、电影、美剧和物理题材,面料舒适、100%纯棉,有黑、白、灰、藏青色,单件 ¥59.9、两件减¥12、四件减¥28、六件减¥42,详见网店商品页介绍。



(上面为部分 T 恤款式)


网店地址:https://fanpinshe.taobao.com


淘口令:复制以下红色内容,然后打开手淘即可购买


范品社,使用¥极客T恤¥抢先预览(长按复制整段文案,打开手机淘宝即可进入活动内容)