国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Volley源碼解析

2019-11-09 17:44:09
字體:
來源:轉載
供稿:網友

Volley是Google開發的一個網絡請求框架,該框架適合進行小而頻繁的網絡請求。 Volley的使用比較簡單,只需幾個簡單的操作就可以實現發送請求。以StringRequest 為例:

//創建一個請求隊列RequestQueue requestQueue = Volley.newRequestQueue(this); String url = "request_url"; //創建StringRequest對象,以Post數據為例 StringRequest request = new StringRequest(Request.Method.POST, url, 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.toString()); } }) { //填寫需要post的表單 @Override PRotected Map<String, String> getParams() throws AuthFailureError { HashMap<String, String> map = new HashMap<>(); map.put("userId", "0"); //測試數據 map.put("sessionId", "0"); return map; } };requestQueue.add(request);

首先需要看看 Volley.newRequestQueue(this) 這句是如何實現的:

public static RequestQueue newRequestQueue(Context context, HttpStack stack) { //緩存路徑 File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR); //代碼省略 if (stack == null) { if (Build.VERSION.SDK_INT >= 9) { stack = new HurlStack(); } else { stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent)); } } //實現請求的類 Network network = new BasicNetwork(stack); //創建一個請求隊列 RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network); queue.start(); return queue; }

這里需要關注的是當SDK版本小于9時,就會使用HttpClientStack來完成請求,否則,則用HurlStack。前者使用的是HttpClient,而后者使用的是HttpURLConnection。 接著,執行了queue.start()語句:

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. for (int i = 0; i < mDispatchers.length; i++) { NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork, mCache, mDelivery); //啟動線程 mDispatchers[i] = networkDispatcher; networkDispatcher.start(); } }

上述代碼中出現了兩個分發器:CacheDispatcher和NetworkDispatcher。它們都是繼承Thread,分別用于處理緩存和網絡請求。其中處理網絡請求的線程有4個。

private static final int DEFAULT_NETWORK_THREAD_POOL_SIZE = 4;

既然是線程的子類,并且都調用了start方法啟動線程,那么就需要看看run方法是如何實現的:

CacheDispatcher

@Override public void run() { //代碼省略 while (true) { try { //不斷地從隊列中讀取請求 final Request<?> request = mCacheQueue.take(); request.addMarker("cache-queue-take"); // 如果請求被取消了,就不再處理 if (request.isCanceled()) { request.finish("cache-discard-canceled"); continue; } // 取出網絡請求的緩存 Cache.Entry entry = mCache.get(request.getCacheKey()); if (entry == null) { request.addMarker("cache-miss"); // 如果找不到,就交由網絡請求線程去處理 mNetworkQueue.put(request); continue; } // 緩存過期,交由網絡請求線程去處理 if (entry.isExpired()) { request.addMarker("cache-hit-expired"); request.setCacheEntry(entry); mNetworkQueue.put(request); continue; } // 命中緩存,寫入數據 request.addMarker("cache-hit"); Response<?> response = request.parseNetworkResponse( new NetworkResponse(entry.data, entry.responseHeaders)); request.addMarker("cache-hit-parsed"); if (!entry.refreshNeeded()) { mDelivery.postResponse(request, response); } else { request.addMarker("cache-hit-refresh-needed"); request.setCacheEntry(entry); response.intermediate = true; //發送請求結果 mDelivery.postResponse(request, response, new Runnable() { @Override public void run() { try { mNetworkQueue.put(request); } catch (InterruptedException e) { } } }); } } catch (InterruptedException e) { // 超時 if (mQuit) { return; } continue; } } }

NetworkDispatcher

public void run() { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); while (true) { long startTimeMs = SystemClock.elapsedRealtime(); Request<?> request; try { // 取出請求 request = mQueue.take(); } catch (InterruptedException e) { // 超時 if (mQuit) { return; } continue; } try { request.addMarker("network-queue-take"); // 如果取消,不做處理 if (request.isCanceled()) { request.finish("network-discard-cancelled"); continue; } addTrafficStatsTag(request); // 執行網絡請求,mNetwork就是之前創建隊列時的BasicNetwork,里面具體實現了網絡請求 NetworkResponse networkResponse = mNetwork.performRequest(request); request.addMarker("network-http-complete"); if (networkResponse.notModified && request.hasHadResponseDelivered()) { request.finish("not-modified"); continue; } // 解析返回結果 Response<?> response = request.parseNetworkResponse(networkResponse); request.addMarker("network-parse-complete"); // 如果可以緩存,則添加到緩存中 if (request.shouldCache() && response.cacheEntry != null) { mCache.put(request.getCacheKey(), response.cacheEntry); request.addMarker("network-cache-written"); } // 回調結果 request.markDelivered(); mDelivery.postResponse(request, response); } catch (VolleyError volleyError) { volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs); parseAndDeliverNetworkError(request, volleyError); } catch (Exception e) { VolleyLog.e(e, "Unhandled exception %s", e.toString()); VolleyError volleyError = new VolleyError(e); volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs); mDelivery.postError(request, volleyError); } }}

接著需要看看請求結果是如何被回調的: mDelivery.postResponse(request, response),其實是調用了ExecutorDelivery中的postResponse方法:

@Override public void postResponse(Request<?> request, Response<?> response, Runnable runnable) { request.markDelivered(); request.addMarker("post-response"); //線程池添加任務 mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, runnable)); }

再看看該任務中的run方法:

@Override public void run() { if (mRequest.isCanceled()) { mRequest.finish("canceled-at-delivery"); return; } if (mResponse.isSuccess()) { //此處會調用Request的onResponse方法,實現回調 mRequest.deliverResponse(mResponse.result); } else { mRequest.deliverError(mResponse.error); } if (mResponse.intermediate) { mRequest.addMarker("intermediate-response"); } else { mRequest.finish("done"); } if (mRunnable != null) { mRunnable.run(); } }

至此,對于網絡請求是如何處理的有了一定的了解。緊接著看看每次添加網絡請求是如何實現的,即add方法:

public <T> Request<T> add(Request<T> request) { request.setRequestQueue(this); synchronized (mCurrentRequests) { //把請求添加到集合 mCurrentRequests.add(request); } // 添加順序 request.setSequence(getSequenceNumber()); request.addMarker("add-to-queue"); // 如果設置不緩存,直接走網絡 if (!request.shouldCache()) { mNetworkQueue.add(request); return request; } // 否則,添加到緩存中,該緩存的鍵值對為cacheKey和request synchronized (mWaitingRequests) { String cacheKey = request.getCacheKey(); if (mWaitingRequests.containsKey(cacheKey)) { //查找是否有相同鍵,取出對應請求 Queue<Request<?>> stagedRequests = mWaitingRequests.get(cacheKey); if (stagedRequests == null) { stagedRequests = new LinkedList<Request<?>>(); } stagedRequests.add(request); mWaitingRequests.put(cacheKey, stagedRequests); if (VolleyLog.DEBUG) { VolleyLog.v("Request for cacheKey=%s is in flight, putting on hold.", cacheKey); } } else { //沒有對應request就設置為null mWaitingRequests.put(cacheKey, null); //添加到處理緩存隊列 mCacheQueue.add(request); } return request; } }
上一篇:const 的作用?

下一篇:2017面試要點

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 金湖县| 赤水市| 临猗县| 滁州市| 邓州市| 宣化县| 方城县| 辽宁省| 松溪县| 阜新| 德兴市| 微博| 区。| 孝昌县| 昆山市| 阿拉尔市| 芮城县| 峨边| 元阳县| 淮南市| 莱西市| 叶城县| 会东县| 井冈山市| 南昌市| 堆龙德庆县| 娱乐| 嘉定区| 五常市| 阳原县| 赤水市| 易门县| 双流县| 临朐县| 靖安县| 平潭县| 黑河市| 陆河县| 平安县| 乐陵市| 马关县|