从官网学习volley框架之执行流程源码分析

在学习的android 系统源码时 发现了volley 这个库,于是就学习学习.

1.volley 官网使用说明地址:volley  从官网就知道volley 简单的使用,优点和缺点

优点:

  • Automatic scheduling of network requests. //自动处理网络请求
  • Multiple concurrent network connections.// 适用多并发
  • Transparent disk and memory response caching with standard HTTP cache coherence. //对请求应答数据进行磁盘和内存中进行缓存
  • Support for request prioritization.// 支持优先级 请求 优先级越高优先处理
  • Cancellation request API. You can cancel a single request, or you can set blocks or scopes of requests to cancel.//可以取消request 实际上只是调用reqeust.cancel()方法把回调方法置空.也可以跟其他组件生命周期进行绑定
  • Ease of customization, for example, for retry and backoff.//可以重连 默认类不做重连 需要自己实现
  • Strong ordering that makes it easy to correctly populate your UI with data fetched asynchronously from the network.//便捷的通过异步请求获取网络数据并分发的ui 线程更新数据 

缺点:

  •  Volley is not suitable for large download or streaming operations, since Volley holds all responses in memory during parsing. For large download operations;// 不适用大数据的处理 因为解析应答数据是在内存进行的说白了就是会消耗大量内存.
  • volley 默认 开五个线程时处理请求,一个缓存线程和四个网络线程 ,所以volley 定位是网络请求频繁的,且应答内容小的.如果网络请求不频繁那需要配置线程数量不然造成资源浪费.

使用

 final RequestQueue requestQueue = Volley.newRequestQueue(this);

        findViewById(R.id.btn_Request).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                StringRequest request = new StringRequest(Request.Method.GET, "https://www.baidu.com/", new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        Log.i("tag", response);
                    }
                }, new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        Log.i("tag", error.getMessage());
                    }
                });
                requestQueue.add(request);


            }
        });
//代码很烂不规范 只是用来分析流程不喜 勿喷

2. 首先用使用Volley 来创建请求队列对象,中间会创建处理缓存对象,处理网络请求对象并开启死循环线程处理,三个集合来存放请求队列.代码如下:

 public static RequestQueue newRequestQueue(Context context, BaseHttpStack stack) {
        BasicNetwork network;
        if (stack == null) {
            if (Build.VERSION.SDK_INT >= 9) {
                network = new BasicNetwork(new HurlStack());
            } else {
         .....
                } catch (NameNotFoundException e) {
                }

                network =
                        new BasicNetwork(
                                new HttpClientStack(AndroidHttpClient.newInstance(userAgent)));
            }
        } else {
            network = new BasicNetwork(stack);
        }

        return newRequestQueue(context, network);
    }
//没用其他的删除 都是9版本之后吧 判断stack 处理网络请求对象是否为空 为空就用HurlStack 
BasicNetWork 只是代理 stack 对象 真正做网络请求的事HurlStack
BasicNetWork关键方法:
 public NetworkResponse performRequest(Request<?> request) throws VolleyError {
        long requestStart = SystemClock.elapsedRealtime();
        while (true) {
            HttpResponse httpResponse = null;
            byte[] responseContents = null;
            List<Header> responseHeaders = Collections.emptyList();
            try {
                // Gather headers.
                Map<String, String> additionalRequestHeaders =
                        getCacheHeaders(request.getCacheEntry());
//这里是做网络请求方法
                httpResponse = mBaseHttpStack.executeRequest(request, additionalRequestHeaders);
//获取响应码 来判断请求结果是怎么样的 来进行不同的处理
                int statusCode = httpResponse.getStatusCode();

                responseHeaders = httpResponse.getHeaders();
                // Handle cache validation. 服务器数据是否修改过 一般都图片或者大的数据进行标识
                if (statusCode == HttpURLConnection.HTTP_NOT_MODIFIED) {
           .....
                }

                // Some responses such as 204s do not have content.  We must check.
                InputStream inputStream = httpResponse.getContent();
                if (inputStream != null) {
      //这个把流读取 存放到byte数组中, 所以不适合对大数据进行处理 不然耗内存 和造成内存抖动
                    responseContents =
                            inputStreamToBytes(inputStream, httpResponse.getContentLength());
                } else {
                    // Add 0 byte response as a way of honestly representing a
                    // no-content request.
                    responseContents = new byte[0];
                }

                // if the request is slow, log it.
                long requestLifetime = SystemClock.elapsedRealtime() - requestStart;
                logSlowRequests(requestLifetime, request, responseContents, statusCode);

                if (statusCode < 200 || statusCode > 299) {
                    throw new IOException();
                }
      
                return new NetworkResponse(
                        statusCode,
                        responseContents,
                        /* notModified= */ false,
                        SystemClock.elapsedRealtime() - requestStart,
                        responseHeaders);
            } catch (SocketTimeoutException e) {
          //这里就是进行网络重新连接请求方法 默认空实现
                attemptRetryOnException("socket", request, new TimeoutError());
            } catch (MalformedURLException e) {
                throw new RuntimeException("Bad URL " + request.getUrl(), e);
            } catch (IOException e) {
                ........
              
        }
    }
而HurlStack 实现就比较简单 这里代码就不贴出来了

3.add 方法调用之后怎么就自动 处理网络请求了呢:

 
 public <T> Request<T> add(Request<T> request) {
        // Tag the request as belonging to this queue and add it to the set of current requests.
        request.setRequestQueue(this);
        synchronized (mCurrentRequests) {
            mCurrentRequests.add(request);
        }

        // Process requests in the order they are added.
    //使用原子类进行自加 如果优先级相同就是fifo 如果优先级高就会往前移动进行插入
        request.setSequence(getSequenceNumber());
        request.addMarker("add-to-queue");
        sendRequestEvent(request, RequestEvent.REQUEST_QUEUED);

        // If the request is uncacheable, skip the cache queue and go straight to the network.
// 默认true 也就是说设置为false 可以不走读缓存这个步骤
        if (!request.shouldCache()) {
            mNetworkQueue.add(request);
            return request;
        }
        mCacheQueue.add(request);
        return request;
    }

从上面代码看来只是对请求添加到请求队列中啊 怎么就自动处理了呢?
那还得从newRequestQueue 说起
  private static RequestQueue newRequestQueue(Context context, Network network) {
//缓存路径
        File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);
        RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
        queue.start();//关键方法
        return queue;
    }

  public void start() {
        stop(); // Make sure any currently running dispatchers are stopped.
        // Create the cache dispatcher and start it.
        mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery);
        mCacheDispatcher.start();

        // Create network dispatchers (and corresponding threads) up to the pool size.默认4个
        for (int i = 0; i < mDispatchers.length; i++) {
            NetworkDispatcher networkDispatcher =
                    new NetworkDispatcher(mNetworkQueue, mNetwork, mCache, mDelivery);
            mDispatchers[i] = networkDispatcher;
            networkDispatcher.start();
        }
    }
CacheDispatcher 和NetworkDispatcher 继承Thread 类那么我们只要看 run 方法就行了 
CacheDispatcher.run:
   @Override
    public void run() {
        if (DEBUG) VolleyLog.v("start new dispatcher");
        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

        // Make a blocking call to initialize the cache.
     //读取之前的缓存数据到内存中或者创建路径
        mCache.initialize();
 //做死循环
        while (true) {
            try {
                processRequest();
            } catch (InterruptedException e) {
                // We may have been interrupted because it was time to quit.
                if (mQuit) {
                    Thread.currentThread().interrupt();
                    return;
                }
                VolleyLog.e(
                        "Ignoring spurious interrupt of CacheDispatcher thread; "
                                + "use quit() to terminate it");
            }
        }
    } 

 private void processRequest() throws InterruptedException {
        // Get a request from the cache triage queue, blocking until
        // at least one is available.
  这里就是能自动处理的原因. 因为使用的是PriorityBlockingQueue 类. take没有元素时堵塞直到add 方法把元素添加进来 ,就然后就进行读取缓存操作.这是生产_消费模式 
        final Request<?> request = mCacheQueue.take();
进行读取缓存操作 ,当内存没有缓存或者内容过期就把请求添加 网络请求队列中.NetworkDispatcher 实现原理跟这个是一样的,所以不用说了.当请求成功或者失败 会调用finish 把这个请求从总的请求队列中移除
        processRequest(request);
    }

4.回调调用 其实回调方式实现也很简单就是通过handler 把Runnable 分发到主线程执行 并调用回调.实现在 ExecutorDelivery类中

5.这里的流程就是 创建队列时会创建缓存线程和网络处理线程 并启动,没有请求时这些线程时堵塞着的,当add 一个请求时缓存线程就会得到这个请求并处理当,当内存没有缓存或者内容过期就交给网络线程处理.请求完后解析响应体进行回调.官网的流程图:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值