从源码分析一次简单的volley请求

从源码分析一次简单的volley请求

RequestQueue mRequestQueue = Volley.newRequestQueue(context);
StringRequest stringRequest = new StringRequest(url, new Listener<String>() {

                    @Override
                    public void onResponse(String arg0) {

                    }
                }, new ErrorListener() {

                    @Override
                    public void onErrorResponse(VolleyError arg0) {

                    }
                });
mRequestQueue .add(stringRequest );

一次简单的字符串网络请求如上,首先构造一个RequestQueue示例,再把请求用到的url,参数等封装到一个Request里面,最后把请求request添加到RequestQueue里就可以了。很简单。那么源码里做了哪些工作呢,现在我们一行一行的来分析。
先看这句Volley.newRequestQueue(context)的源码里在做什么呢。
Volley里重载了好多个newRequestQueue()静态方法,最终调用了

 public static RequestQueue newRequestQueue(Context context, HttpStack stack, int maxDiskCacheBytes) {
        File cacheDir = new File(context.getCacheDir(), "volley");
        String userAgent = "volley/0";

        try {
            String network = context.getPackageName();
            PackageInfo queue = context.getPackageManager().getPackageInfo(network, 0);
            userAgent = network + "/" + queue.versionCode;
        } catch (NameNotFoundException var7) {
            ;
        }

        if(stack == null) {
            if(VERSION.SDK_INT >= 9) {
                stack = new HurlStack();
            } else {
                stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
            }
        }

        BasicNetwork network1 = new BasicNetwork((HttpStack)stack);
        RequestQueue queue1;
        if(maxDiskCacheBytes <= -1) {
            queue1 = new RequestQueue(new DiskBasedCache(cacheDir), network1);
        } else {
            queue1 = new RequestQueue(new DiskBasedCache(cacheDir, maxDiskCacheBytes), network1);
        }

        queue1.start();
        return queue1;
    }

在这个方法里首先构建了缓存文件cacheDir ,然后就是构建网络请求的真正执行者stack,它分了版本,在sdk9之后,创建HurlStack,他是封装了HttpURLConnection来执行请求,sdk9.0之前创建HttpClientStack实例,他是封装了HttpClient来执行请求,这俩个类大家应该是熟悉的,为了统一两个类造成的差别,又把他们封装到了一个BasicNetwork中,由BasicNetwork来统一执行请求,这里用到了设计模式中的模板模式,HttpStack是个接口,里面定义了

HttpResponse performRequest(Request<?> var1, Map<String, String> var2);

BasicNetwork实现了Network接口,Network也只有一个接口

NetworkResponse performRequest(Request<?> var1)

一个请求的过程是由BasicNetwork调用HurlStack的performRequest,HurlStack再由其具体的子类HttpURLConnection或者HttpClient通过performRequest来真正的执行请求。
回到newRequestQueue(Context context, HttpStack stack, int maxDiskCacheBytes)这个方法,接下来是构建 RequestQueue实例,在构造函数里带着network1,估计请求执行的开始点又转移到RequestQueue中了。
接下来我们就来分析一下RequestQueue类。

public RequestQueue(Cache cache, Network network, int threadPoolSize, ResponseDelivery delivery) {
        this.mSequenceGenerator = new AtomicInteger();
        this.mWaitingRequests = new HashMap();//存放相同url的请求
        this.mCurrentRequests = new HashSet();//存放所有的请求
        this.mCacheQueue = new PriorityBlockingQueue();//存放不重复的请求
        this.mNetworkQueue = new PriorityBlockingQueue();//存放要执行的网络请求
        this.mFinishedListeners = new ArrayList();
        this.mCache = cache;
        this.mNetwork = network;//重Volley类传过来执行请求的类
        this.mDispatchers = new NetworkDispatcher[threadPoolSize];//NetworkDispatcher是封装好的请求执行线程池,thredpoolsize默认是4。
        this.mDelivery = delivery;
}

接下来我们再分析RequestQueue的start()方法源码,这个很重要。

public void start() {
        this.stop();
        this.mCacheDispatcher = new CacheDispatcher(this.mCacheQueue, this.mNetworkQueue, this.mCache, this.mDelivery);
        this.mCacheDispatcher.start();

        for(int i = 0; i < this.mDispatchers.length; ++i) {
            NetworkDispatcher networkDispatcher = new NetworkDispatcher(this.mNetworkQueue, this.mNetwork, this.mCache, this.mDelivery);
            this.mDispatchers[i] = networkDispatcher;
            networkDispatcher.start();
        }

    }

CacheDispatcher这个是获取请求缓存结果的一个线程,重复的请求可以在这里直接获得结果。NetworkDispatcher在上面分析过其功能。从上面分析可知,queue1.start()之后,默认将会有5个线程开启,一个缓存线程,4个网络工作线程。Volley的整个机制就开始跑起来了,有网络请求的时候,就构造好request后,通过requeQueue的add()添加进去,至于这个请求是否直接或者请求结果,还是进行网络请求,则由requestQueue去调度了。所以接下来我们再分析一下add()方法,看看他是怎么调度网络请求的。

 public <T> Request<T> add(Request<T> request) {
        request.setRequestQueue(this);
        Set var2 = this.mCurrentRequests;
        synchronized(this.mCurrentRequests) {
            this.mCurrentRequests.add(request);//所有的请求都会添加到mCurrentRequests
        }
        request.setSequence(this.getSequenceNumber());//确定请求的序列号
        request.addMarker("add-to-queue");
//从这里开始有调度策略了
        if(!request.shouldCache()) 
{              //不需要缓存结果的直接扔给网络队列去网络请求
            this.mNetworkQueue.add(request);
            return request;
        } else {
            Map var7 = this.mWaitingRequests;
            synchronized(this.mWaitingRequests) {
                String cacheKey = request.getCacheKey();//返回request的url作为缓存key
                if(this.mWaitingRequests.containsKey(cacheKey)) {
                     //重复的请求放到相同key的队列里
                    Object stagedRequests = (Queue)this.mWaitingRequests.get(cacheKey);
                    if(stagedRequests == null) {
                        stagedRequests = new LinkedList();
                    }

                    ((Queue)stagedRequests).add(request);
                    this.mWaitingRequests.put(cacheKey, stagedRequests);
                    if(VolleyLog.DEBUG) {

                    }
                } else {
                    this.mWaitingRequests.put(cacheKey, (Object)null);
                    this.mCacheQueue.add(request);
                }

                return request;
            }
        }
    }

最后我们再分析CacheDispatcher和NetworkDispatcher。
再requestQueue的start()方法中,创建了这两个类的,开启了线程。
创建CacheDispatcher时候CacheDispatcher(this.mCacheQueue, this.mNetworkQueue, this.mCache, this.mDelivery);
带进去了
this.mCacheQueue = new PriorityBlockingQueue();//存放不重复的请求
this.mNetworkQueue = new PriorityBlockingQueue();//存放要执行的网络请求
这两个参数,再看他的run()方法

    public void run() {
        if(DEBUG) {
            VolleyLog.v("start new dispatcher", new Object[0]);
        }

        Process.setThreadPriority(10);
        this.mCache.initialize();

        while(true) {
            while(true) {
                while(true) {
                    while(true) {
                        try {
                            while(true) {
                             //从对列中取出一个请求
                                final Request e = (Request)this.mCacheQueue.take();
                                e.addMarker("cache-queue-take");
                                if(e.isCanceled()) {


//请求取消了就结束这个请求
  e.finish("cache-discard-canceled");
                                } else {

                                   Entry entry = this.mCache.get(e.getCacheKey());
                                   //检查缓存里是否有对应结果了
 if(entry == null) {
                                        e.addMarker("cache-miss");
                                    //没有缓存就扔进网络执行对列里    
this.mNetworkQueue.put(e);
                                    } else if(entry.isExpired()) {
                                          //缓存过期也扔进网络执行对列里再请求一次  
                                        e.addMarker("cache-hit-expired");
                                        e.setCacheEntry(entry);
                                        this.mNetworkQueue.put(e);
                                    } else {
                                        e.addMarker("cache-hit");
                                        Response response = e.parseNetworkResponse(new NetworkResponse(entry.data, entry.responseHeaders));
                                        e.addMarker("cache-hit-parsed");
                                        if(entry.refreshNeeded()) {
//如果需要刷新,也会扔到网络执行对列里执行
                                            e.addMarker("cache-hit-refresh-needed");
                                            e.setCacheEntry(entry);
                                            response.intermediate = true;
                                            this.mDelivery.postResponse(e, response, new Runnable() {
                                                public void run() {
                                                    try {
                                                        CacheDispatcher.this.mNetworkQueue.put(e);
                                                    } catch (InterruptedException var2) {
                                                        ;
                                                    }

                                                }
                                            });
                                        } else {
                         //没有上述约束,直接传递结果到主线程              
                               this.mDelivery.postResponse(e, response);

再看看NetworkDispatcher怎么执行的

    public NetworkDispatcher(BlockingQueue<Request<?>> queue, Network network, Cache cache, ResponseDelivery delivery) {
        this.mQueue = queue;//从requestQueue传进来的请求对列
        this.mNetwork = network;//网络请求的执行者
        this.mCache = cache;
        this.mDelivery = delivery;
    }

再看看他的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);
                       //由mNetwork去执行网络请求
                    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);
            }
        }
    }

到这里,volley的网络请求机制就基本出来了。

再分享一个点,Request有好多个子类,如StringRequest,JsonRequest,ImageRequest
,他们有什么区别呢,在上面有行解析NetworkResponse 的代码
esponse volleyError1 = request.parseNetworkResponse(e);
这几个子类解析出来对应的结果都不同,
StringRequest

 protected Response<String> parseNetworkResponse(NetworkResponse response) {
        String parsed;
        try {
            parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
        } catch (UnsupportedEncodingException var4) {
            parsed = new String(response.data);
        }

        return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));
    }

就是解析出了一个字符串。

在看看JsonobjectRequest

    protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
        try {
            String je = new String(response.data, HttpHeaderParser.parseCharset(response.headers, "utf-8"));
            return Response.success(new JSONObject(je), HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException var3) {
            return Response.error(new ParseError(var3));
        } catch (JSONException var4) {
            return Response.error(new ParseError(var4));
        }
}

返回给主线程的就是个jsonobject

最后看看ImageRequest

    private Response<Bitmap> doParse(NetworkResponse response) {
        byte[] data = response.data;
        Options decodeOptions = new Options();
        Bitmap bitmap = null;
        if(this.mMaxWidth == 0 && this.mMaxHeight == 0) {
            decodeOptions.inPreferredConfig = this.mDecodeConfig;
            bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, decodeOptions);
        } else {
            decodeOptions.inJustDecodeBounds = true;
            BitmapFactory.decodeByteArray(data, 0, data.length, decodeOptions);
            int actualWidth = decodeOptions.outWidth;
            int actualHeight = decodeOptions.outHeight;
            int desiredWidth = getResizedDimension(this.mMaxWidth, this.mMaxHeight, actualWidth, actualHeight, this.mScaleType);
            int desiredHeight = getResizedDimension(this.mMaxHeight, this.mMaxWidth, actualHeight, actualWidth, this.mScaleType);
            decodeOptions.inJustDecodeBounds = false;
            decodeOptions.inSampleSize = findBestSampleSize(actualWidth, actualHeight, desiredWidth, desiredHeight);
            Bitmap tempBitmap = BitmapFactory.decodeByteArray(data, 0, data.length, decodeOptions);
            if(tempBitmap == null || tempBitmap.getWidth() <= desiredWidth && tempBitmap.getHeight() <= desiredHeight) {
                bitmap = tempBitmap;
            } else {
                bitmap = Bitmap.createScaledBitmap(tempBitmap, desiredWidth, desiredHeight, true);
                tempBitmap.recycle();
            }
        }

        return bitmap == null?Response.error(new ParseError(response)):Response.success(bitmap, HttpHeaderParser.parseCacheHeaders(response));
    }

最后返回了一个bitmap

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值