为了账号安全,请及时绑定邮箱和手机立即绑定

Vollery源码阅读(—)

标签:
Android

1. 创建获取 RequestQueue 对象

RequestQueue mQueue = Volley.newRequestQueue(this);

开始进入:::
Vollery # newRequestQueue()

public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
        .....        if (stack == null) {            if (VERSION.SDK_INT >= 9) {
                stack = new HurlStack();
            } else {
                stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
            }
        }

        Network network = new BasicNetwork((HttpStack)stack);
        RequestQueue queue = new RequestQueue(new NoCache(), network);
        queue.start();        return queue;
    }

看到我开始罗列代码了,不要慌,还好不长,在能力范围内:

webp

image

刚开始就根据不同的Android 系统版本,创建不同的对象,我们先可以大概了解一下 HurlStack 和  HttpClientStack 是啥?

HurlStack.java

public class HurlStack implements HttpStack {
      ....    public HttpResponse performRequest(Request<?> request, 
                      Map<String, String>  additionalHeaders) {
            ....
            URL parsedUrl = new URL(url);
            HttpURLConnection connection = this.openConnection(parsedUrl, request); 
           ....
    }

HttpClientStack.java

public class HttpClientStack implements HttpStack {    protected final HttpClient mClient;
    ...    public HttpResponse performRequest(Request<?> request, 
                         Map<String, String> additionalHeaders)  {
          ....         return this.mClient.execute(httpRequest)
    }
}

HttpStack.java

public interface HttpStack {    HttpResponse performRequest(Request<?> var1, Map<String, String> var2) ;
}

看到这里我们大概明白了,原来是根据不同的系统版本,确定最终选择进行的网络请求,那为什么大于9 用 HttpUrlConnection 小于9用 HttpClient 呢?在这里不过多介绍了,网上一搜就知道了。

Ok,那我们继续向下走,回到上面的代码,为了方便查看,我重新粘贴一份代码下来:

public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
        .....        if (stack == null) {            if (VERSION.SDK_INT >= 9) {
                stack = new HurlStack();
            } else {
                stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
            }
        }        //HttpStack 又一次被封装为Network接口类型
        Network network = new BasicNetwork((HttpStack)stack);
        RequestQueue queue = new RequestQueue(new NoCache(), network);
        queue.start();        return queue;
    }

Network.java

public interface Network {    NetworkResponse performRequest(Request<?> var1) throws VolleyError;
}

哦 原来是接口,它的实现类 BasicNetwork
BasicNetwork.java

public class BasicNetwork implements Network {    //将网络请求的实例传入,方便后面的调用
  public BasicNetwork(HttpStack httpStack) {        this(httpStack, new ByteArrayPool(DEFAULT_POOL_SIZE));
    }
   ....
}

目前而止,那么它们之间的关系是啥样的呢,我画了一张图:

webp

image.png


很清晰吧,目前我们先不考虑这个 BasicNetwork 类中干了什么,我们先根据代码的思路一步步向下走,保证我们整体主干不变,避免陷入只见树木不见森林的局势。


Ok,我们再次回到原来的代码:

public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
        .....        if (stack == null) {            if (VERSION.SDK_INT >= 9) {
                stack = new HurlStack();
            } else {
                stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
            }
        }        //HttpStack 又一次被封装为Network接口类型,
       //创建BasicNetwork调用了构造方法是一个参数的
        Network network = new BasicNetwork((HttpStack)stack);      //到这里了...........
      //创建一个 请求队列 RequestQueue,并且在构造函数中,传入了两个
     //参数,好,我们接下来就要去RequestQueue.java类中看一眼了。
        RequestQueue queue = new RequestQueue(new NoCache(), network);
        queue.start();        return queue;
    }

RequestQueue.java

public RequestQueue(Cache cache, Network network) {        this(cache, network, 2);
    }public RequestQueue(Cache cache, Network network, int threadPoolSize) {        this(cache, network, threadPoolSize, new ExecutorDelivery(new Handler(Looper.getMainLooper())));
    }public RequestQueue(Cache cache, Network network, int threadPoolSize, ResponseDelivery delivery) {        this.mSequenceGenerator = new AtomicInteger();        this.mWaitingRequests = new HashMap();        this.mCurrentRequests = new HashSet();        this.mCacheQueue = new PriorityBlockingQueue();        this.mNetworkQueue = new PriorityBlockingQueue();        this.mCache = cache;        this.mNetwork = network;        this.mDispatchers = new NetworkDispatcher[threadPoolSize];        this.mDelivery = delivery;
    }

在构造方法中,传入一个Cache 对象,network 对象,默认初始化一个threadPoolSize = 2,还有一系列初始化操作.

Ok,再次返回我们之前的代码:

   ....
   RequestQueue queue = new RequestQueue(new NoCache(), network);
  queue.start();

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 类。调用四个参数的构造方法。并调用了 start() 方法。
接下来,我们就认识下 CacheDispatcher.java 类:

//原来它是一个线程public class CacheDispatcher extends Thread {//缓存队列,用BlockingQueue 管理存储private final BlockingQueue<Request<?>> mCacheQueue;   public CacheDispatcher(BlockingQueue<Request<?>> cacheQueue, BlockingQueue<Request<?>> networkQueue, Cache cache, ResponseDelivery delivery) {       //参数赋值
        this.mCacheQueue = cacheQueue;        this.mNetworkQueue = networkQueue;        this.mCache = cache;        this.mDelivery = delivery;
    }//调用start 方法必定调用run 方法
 public void run() {
        .....
        Process.setThreadPriority(10);      //这里初始化缓存,还记得我们之前默认传入了一个 NoCache 吗?
    //这里Cache 是接口,子类有两种NoCache 和 DiskBasedCache两种
        this.mCache.initialize();      //嵌套了好多循环啊......因为要不断去读取是否有任务嘛,没有的时候就一直等待
        while(true) {            while(true) {                while(true) {                    while(true) {                        try {                          // 表示从缓存队列中取出一个 Request, 那第一次肯定没有啊,就一直等待......
                            final Request<?> request = (Request)this.mCacheQueue.take();
                         .....这里我先省略了,因为还没真正到这一步
}

OK,返回到我们之前的操作:
RequestQueue.java

private NetworkDispatcher[] mDispatchers ;private static final int DEFAULT_NETWORK_THREAD_POOL_SIZE = 2; public RequestQueue(Cache cache, Network network, int threadPoolSize, ResponseDelivery delivery) {
         ....        this.mDispatchers = new NetworkDispatcher[threadPoolSize];
        ....
    }public void start() {        this.stop();        this.mCacheDispatcher = new CacheDispatcher(this.mCacheQueue, this.mNetworkQueue, this.mCache, this.mDelivery);        this.mCacheDispatcher.start();      //到这里啦,
      //从构造方法我们可以得知 mDispatchers.length = 2 ,上
        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();
        }

    }

循环遍历生成2 个 NetworkDispatcher 对象,并将 NetworkDispatcher 对象存储在一个 mDispatchers 的数组中去了,最后调用了 start 方法。
Ok,那接下来我们就看下这个 NetworkDispatcher.java 类了。

NetworkDispatcher.java

public class NetworkDispatcher extends Thread {      // 网络请求队列
       private final BlockingQueue<Request<?>> mQueue;        //对象初始化
        public NetworkDispatcher(BlockingQueue<Request<?>> queue, Network network, Cache cache, ResponseDelivery delivery) {        this.mQueue = queue;        this.mNetwork = network;        this.mCache = cache;        this.mDelivery = delivery;
    }   
//既然是线程,调用 start 方法,必定调用 run 方法public void run() {
        Process.setThreadPriority(10);      //线程也是,既然要做网络请求,就要一直等待获取
        while(true) {
            Request request;            while(true) {                try {                  // 从网络请求队列中获取任务,那一开始我们初始化肯定没东西,队列里没请求任务
                    request = (Request)this.mQueue.take();                    break;
                } catch (InterruptedException var4) {                    if (this.mQuit) {                        return;
                    }
                }
            }
      .....底部代码我也省略了,因为都是获取到请求之后所做的处理

至此,对于RequestQueue  的初始化第一步我们完成了对它的了解,你明白了吗? 下一篇我们针对 mQueue.add(request) 真正需要进行网络请求进行继续分析。如果这篇文章有帮助到你,给个赞就是我最大的鼓励了,比心。



作者:糖葫芦_倩倩
链接:https://www.jianshu.com/p/6b55505dd2fe


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消