Vollery源碼閱讀(—)

寫在最前面的話:送給還在迷茫看不懂的童鞋,跟着我一步步看,小白也能看懂,從而對總體有一個把握,分析的開始以基本使用爲切入點,一步步深刻。java

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;
    }
複製代碼

看到我開始羅列代碼了,不要慌,還好不長,在能力範圍內:緩存

image

剛開始就根據不一樣的Android 系統版本,建立不一樣的對象,咱們先能夠大概瞭解一下 HurlStackHttpClientStack 是啥?bash

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.javaoop

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

看到這裏咱們大概明白了,原來是根據不一樣的系統版本,肯定最終選擇進行的網絡請求,那爲何大於9 用 HttpUrlConnection 小於9用 HttpClient 呢?在這裏不過多介紹了,網上一搜就知道了。ui

Ok,那咱們繼續向下走,回到上面的代碼,爲了方便查看,我從新粘貼一份代碼下來:this

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.javaurl

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));
    }
   ....
}
複製代碼

目前而止,那麼它們之間的關係是啥樣的呢,我畫了一張圖:

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) 真正須要進行網絡請求進行繼續分析。若是這篇文章有幫助到你,給個贊就是我最大的鼓勵了,比心💗。

相關文章
相關標籤/搜索