Android Volley框架使用源碼分享
過(guò)去在Android上網(wǎng)絡(luò)通信都是使用的Xutils 因?yàn)橛盟梢皂樀捞幚砹藞D片和網(wǎng)絡(luò)這兩個(gè)方面,后來(lái)發(fā)覺(jué)Xutils里面使用的是HttpClient 而Google在6.0的版本上已經(jīng)把HttpClient廢除了,所以開(kāi)始尋找新的網(wǎng)絡(luò)框架,okhttp也用過(guò),但是它是在作用在UI線程,使用起來(lái)還需要用handler 所以就先用著Volley框架了。 這里我先分析下Volley框架的簡(jiǎn)單網(wǎng)絡(luò)請(qǐng)求的源碼。
使用Volley請(qǐng)求網(wǎng)絡(luò)數(shù)據(jù)的簡(jiǎn)單過(guò)程:
RequestQueue queue = Volley.newRequestQueue(this); //實(shí)例化一個(gè)請(qǐng)求隊(duì)列 Google推薦寫(xiě)一個(gè)單例類(lèi) 獲取唯一一個(gè)隊(duì)列
StringRequest request = new StringRequest(Request.Method.POST, url1, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Toast.makeText(MainActivity.this, "success"+response, Toast.LENGTH_SHORT).show();
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(MainActivity.this, "失敗了"+error.getMessage(), Toast.LENGTH_SHORT).show();
}
}){
@Override
protected Map<String, String> getParams() throws AuthFailureError { //重寫(xiě)這個(gè)函數(shù)提交參數(shù) 也可以重寫(xiě)一個(gè)Request實(shí)現(xiàn)這個(gè)方法
Map<String,String> params = new HashMap<>();
params.put(aaa+"name","1233555"); //參數(shù)
return params;
}
};
queue.add(request);
請(qǐng)求的處理在newRequestQueue的時(shí)候就開(kāi)始執(zhí)行了 只不過(guò)那時(shí)候請(qǐng)求隊(duì)列中還沒(méi)有請(qǐng)求 所以阻塞了 當(dāng) add的方法執(zhí)行時(shí) 才開(kāi)始真正請(qǐng)求網(wǎng)絡(luò)
所以我們先來(lái)看 queue.add(request) 方法
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); //在當(dāng)前隊(duì)列中加入
}
// Process requests in the order they are added.
request.setSequence(getSequenceNumber());
request.addMarker("add-to-queue"); //設(shè)置標(biāo)志
// If the request is uncacheable, skip the cache queue and go straight to the network.
if (!request.shouldCache()) { //根據(jù)是否需要緩存 如果不需要緩存 就直接加入網(wǎng)絡(luò)任務(wù)隊(duì)列中 然后返回 如果需要緩存 那么在下面代碼中加入緩存隊(duì)列 默認(rèn)是需要緩存的
mNetworkQueue.add(request);
return request;
}
// Insert request into stage if there's already a request with the same cache key in flight.
synchronized (mWaitingRequests) {
String cacheKey = request.getCacheKey();
if (mWaitingRequests.containsKey(cacheKey)) { //判斷當(dāng)前正在被處理并可以緩存的請(qǐng)求中是否包含該請(qǐng)求的key 如果包含說(shuō)明已經(jīng)有一個(gè)相同的請(qǐng)求 那么就加入到其中
// There is already a request in flight. Queue up.
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 { //如果不包含 加入一個(gè)空的請(qǐng)求到 暫存隊(duì)列中 然后加入到緩存隊(duì)列中
// Insert 'null' queue for this cacheKey, indicating there is now a request in
// flight.
mWaitingRequests.put(cacheKey, null);
mCacheQueue.add(request);
}
return request;
}
}
分析add方法 首先加入到mCurrentRequests集合中 這個(gè)集合存放所有這個(gè)隊(duì)列所處理的請(qǐng)求 然后判斷這個(gè)請(qǐng)求是否需要緩存,如果不需要緩存,那么直接加入mNetworkQueue隊(duì)列中等待處理即可,如果需要那么最終加入到mCacheQueue隊(duì)列中,因?yàn)镽equestQueue在處理請(qǐng)求時(shí)總會(huì)先處理緩存的任務(wù),在處理緩存時(shí)如果第一次處理沒(méi)有緩存還是會(huì)加入mNetworkQueue隊(duì)列中處理,如果有緩存那么就直接獲取緩存了,之后判斷當(dāng)前的請(qǐng)求中是否有相同的請(qǐng)求,如果有的話那么就把這個(gè)請(qǐng)求加入到暫存集合中,如果沒(méi)有那么就加入一個(gè)空的到請(qǐng)求到暫存隊(duì)列中,用來(lái)以后判斷是否有和這個(gè)請(qǐng)求相同的請(qǐng)求,然后加入緩存隊(duì)列中即可。
然后我們來(lái)看RequstQueue的創(chuàng)建過(guò)程
public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR); //創(chuàng)建一個(gè)文件用于緩存
String userAgent = "volley/0"; //用戶(hù)代理初始化
try {
String packageName = context.getPackageName();
PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
userAgent = packageName + "/" + info.versionCode; //用戶(hù)代理為app包名+版本號(hào)
} catch (NameNotFoundException e) {
}
if (stack == null) { //如果沒(méi)傳入HttpStack 那么采用下述默認(rèn)的 這里可以自行重寫(xiě)擴(kuò)展HttpStack 體現(xiàn)了該框架的高擴(kuò)展性
if (Build.VERSION.SDK_INT >= 9) { //如果sdk版本高于2.3 采用HurlStack 內(nèi)部是httpUrlConnection實(shí)現(xiàn)
stack = new HurlStack();
} else { //如果版本低于2.3 采用httpClientStack
// Prior to Gingerbread, HttpUrlConnection was unreliable.
// See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
}
}
Network network = new BasicNetwork(stack); //創(chuàng)建一個(gè)網(wǎng)絡(luò)工作 僅僅作用于請(qǐng)求網(wǎng)絡(luò)
RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network); //實(shí)例化一個(gè)請(qǐng)求隊(duì)列 傳入?yún)?shù)
queue.start();
return queue;
}
</pre><pre code_snippet_id="1680121" snippet_file_name="blog_20160512_5_2241745" name="code" class="java">public RequestQueue(Cache cache, Network network, int threadPoolSize) { //構(gòu)造函數(shù) 會(huì)創(chuàng)建默認(rèn)的ExecutorDelivery 用于回調(diào)
this(cache, network, threadPoolSize,
new ExecutorDelivery(new Handler(Looper.getMainLooper())));
}
RequestQueue的創(chuàng)建過(guò)程也比較簡(jiǎn)單 根據(jù)sdk版本號(hào)判斷使用HttpURLConnection還是HttpClient 因?yàn)樵?.3之前 httpUrlConnection有一個(gè)重大的bug 所以使用HttpClient代替,而httpUrlConnection體積小 支持gzip壓縮和緩存,并且速度相對(duì)httpClient快 并逐漸優(yōu)化 所以選擇httpUrlConnection 之后根據(jù)創(chuàng)建的NetWork 創(chuàng)建RequestQueue隊(duì)列 然后開(kāi)啟即可
之后我們查看 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); //創(chuàng)建一個(gè)緩存調(diào)度器 是一個(gè)線程 start后執(zhí)行run方法
mCacheDispatcher.start();
// Create network dispatchers (and corresponding threads) up to the pool size.
for (int i = 0; i < mDispatchers.length; i++) { //默認(rèn)會(huì)有4個(gè)NetworkDispatcher 為了提高效率 執(zhí)行netWorkQueue里的request
NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,
mCache, mDelivery);
mDispatchers[i] = networkDispatcher;
networkDispatcher.start();
}
}
這個(gè)方法 先執(zhí)行緩存調(diào)度器線程然后執(zhí)行4個(gè)網(wǎng)絡(luò)工作調(diào)度器線程,因?yàn)樵诰彺嬲{(diào)度器中 會(huì)判斷是否緩存過(guò),如果緩存過(guò)并且沒(méi)過(guò)期,就直接復(fù)用緩存的,不把任務(wù)加入netWordQueue中 所以下面的NetWork調(diào)度器線程就會(huì)取不到請(qǐng)求而阻塞,不會(huì)執(zhí)行,而如果沒(méi)有緩存,緩存調(diào)度器線程中就會(huì)把請(qǐng)求加入NetWork隊(duì)列中,下面的netWork調(diào)度器就會(huì)取到該請(qǐng)求并執(zhí)行了
我們仔細(xì)看一下CacheDispatcher線程的源碼:
run方法的代碼比較長(zhǎng) 我們分開(kāi)來(lái)看 先看第一部分:
@Override
public void run() {
if (DEBUG) VolleyLog.v("start new dispatcher");
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); //設(shè)置線程的優(yōu)先級(jí) 值為10
// Make a blocking call to initialize the cache.
mCache.initialize(); //初始化一下緩存
while (true) {
try {
// Get a request from the cache triage queue, blocking until
// at least one is available.
final Request<?> request = mCacheQueue.take(); //從緩存隊(duì)列取出一個(gè)請(qǐng)求 如果沒(méi)有則會(huì)阻塞
request.addMarker("cache-queue-take"); //添加一個(gè)標(biāo)記
// If the request has been canceled, don't bother dispatching it.
if (request.isCanceled()) {
request.finish("cache-discard-canceled");
continue;
}
// Attempt to retrieve this item from cache.
Cache.Entry entry = mCache.get(request.getCacheKey()); //從緩存中讀取緩存
if (entry == null) { //如果沒(méi)讀取到緩存
request.addMarker("cache-miss"); //添加緩存miss標(biāo)記
// Cache miss; send off to the network dispatcher.
mNetworkQueue.put(request); //換區(qū)緩存失敗 添加到netWork中等待請(qǐng)求
continue;
}
// If it is completely expired, just send it to the network.
if (entry.isExpired()) { //判斷緩存是否過(guò)期了 如果過(guò)期了 那么就添加到netWork中等待請(qǐng)求
request.addMarker("cache-hit-expired");
request.setCacheEntry(entry);
mNetworkQueue.put(request);
continue;
}
第二部分 :
// We have a cache hit; parse its data for delivery back to the request.
request.addMarker("cache-hit"); //執(zhí)行到了這里說(shuō)明緩存沒(méi)有過(guò)期 并且可以使用
Response<?> response = request.parseNetworkResponse( //把讀取到的緩存內(nèi)容解析成Response對(duì)象
new NetworkResponse(entry.data, entry.responseHeaders));
request.addMarker("cache-hit-parsed"); //添加標(biāo)記
if (!entry.refreshNeeded()) { //如果緩存不需要刷新 直接調(diào)用 mDelivery.postResponse方法 在其中會(huì)回調(diào)request的listener接口
// Completely unexpired cache hit. Just deliver the response.
mDelivery.postResponse(request, response);
} else { //如果需要刷新 把請(qǐng)求加入mNetworkQueue中 等待請(qǐng)求
// Soft-expired cache hit. We can deliver the cached response,
// but we need to also send the request to the network for
// refreshing.
request.addMarker("cache-hit-refresh-needed");
request.setCacheEntry(entry);
// Mark the response as intermediate.
response.intermediate = true;
// Post the intermediate response back to the user and have
// the delivery then forward the request along to the network.
mDelivery.postResponse(request, response, new Runnable() {
@Override
public void run() {
try {
mNetworkQueue.put(request);
} catch (InterruptedException e) {
// Not much we can do about this.
}
}
});
}
} catch (InterruptedException e) {
// We may have been interrupted because it was time to quit.
if (mQuit) {
return;
}
continue;
}
}
}
上面代碼的具體過(guò)程也很簡(jiǎn)單 首先從緩存請(qǐng)求隊(duì)列取出一個(gè)請(qǐng)求,在緩存中看看有沒(méi)有該請(qǐng)求的緩存,如果沒(méi)有 那么 請(qǐng)求放入NetWork調(diào)度器中 等待調(diào)用 如果有 也分幾種情況 如果獲取到的是空,放入NetWOrk 如果過(guò)期 放入 NetWork 如果不需要刷新 就直接從緩存獲取響應(yīng)信息并解析 然后用mDelivery回調(diào)接口即可 如果需要刷新 放入NetWOrd隊(duì)列等待調(diào)用。。。
我們?cè)賮?lái)看看NetworkDispatcher 線程的代碼就可以了 類(lèi)似于CacheDispatcher的代碼:
@Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); //設(shè)置優(yōu)先級(jí) 10
while (true) {
long startTimeMs = SystemClock.elapsedRealtime(); //獲取請(qǐng)求執(zhí)行開(kāi)始時(shí)間
Request<?> request;
try {
// Take a request from the queue.
request = mQueue.take(); //從隊(duì)列獲取一個(gè)請(qǐng)求 沒(méi)有則阻塞
} catch (InterruptedException e) {
// We may have been interrupted because it was time to quit.
if (mQuit) {
return;
}
continue;
}
try {
request.addMarker("network-queue-take");
// If the request was cancelled already, do not perform the
// network request.
if (request.isCanceled()) {
request.finish("network-discard-cancelled");
continue;
}
addTrafficStatsTag(request);
// Perform the network request.
NetworkResponse networkResponse = mNetwork.performRequest(request); //真正執(zhí)行請(qǐng)求的函數(shù) 并返回響應(yīng)
request.addMarker("network-http-complete");
// If the server returned 304 AND we delivered a response already,
// we're done -- don't deliver a second identical response.
if (networkResponse.notModified && request.hasHadResponseDelivered()) {
request.finish("not-modified");
continue;
}
// Parse the response here on the worker thread.
Response<?> response = request.parseNetworkResponse(networkResponse); //解析響應(yīng)
request.addMarker("network-parse-complete");
// Write to cache if applicable.
// TODO: Only update cache metadata instead of entire record for 304s.
if (request.shouldCache() && response.cacheEntry != null) { //如果需要緩存 那么把響應(yīng)的信息存入緩存中
mCache.put(request.getCacheKey(), response.cacheEntry);
request.addMarker("network-cache-written");
}
// Post the response back.
request.markDelivered();
mDelivery.postResponse(request, response); //之后回調(diào)一些方法
} catch (VolleyError volleyError) {
volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs);
parseAndDeliverNetworkError(request, volleyError); //回調(diào)錯(cuò)誤接口
} 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); //回調(diào)錯(cuò)誤接口
}
}
}
NetworkDispatcher 線程的執(zhí)行過(guò)程 先從 networkDispatch中獲取一個(gè)請(qǐng)求 然后判斷 是否取消了 如果沒(méi)有 那么就執(zhí)行NetWOrk的performRequest方法 執(zhí)行http請(qǐng)求,這個(gè)函數(shù)內(nèi)部才是真正的請(qǐng)求數(shù)據(jù) ,請(qǐng)求后 根據(jù)設(shè)置的shouldCache標(biāo)志 判斷是否放入緩存中 之后回調(diào)一些接口方法 即可 這樣就完成了一個(gè)請(qǐng)求
最后我們看一看NetWork類(lèi)mNetwork.performRequest(request)方法是如何提交請(qǐng)求的吧 代碼比較長(zhǎng) 但是不難:
@Override
public NetworkResponse performRequest(Request<?> request) throws VolleyError {
long requestStart = SystemClock.elapsedRealtime(); //記錄開(kāi)始時(shí)間
while (true) {
HttpResponse httpResponse = null;
byte[] responseContents = null;
Map<String, String> responseHeaders = Collections.emptyMap(); //初始化響應(yīng)頭為空
try {
// Gather headers.
Map<String, String> headers = new HashMap<String, String>(); //請(qǐng)求頭
addCacheHeaders(headers, request.getCacheEntry()); //根據(jù)緩存添加請(qǐng)求頭
httpResponse = mHttpStack.performRequest(request, headers); //調(diào)用HttpStack的方法請(qǐng)求網(wǎng)絡(luò)
StatusLine statusLine = httpResponse.getStatusLine();
int statusCode = statusLine.getStatusCode();
responseHeaders = convertHeaders(httpResponse.getAllHeaders()); //獲取響應(yīng)頭
// Handle cache validation.
if (statusCode == HttpStatus.SC_NOT_MODIFIED) { //如果為304 讀取的緩存
Entry entry = request.getCacheEntry(); //查看以前是否緩存過(guò)
if (entry == null) { //如果以前緩存的為空 那么 說(shuō)明上次緩存的請(qǐng)求也為空 直接返回response
return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, null,
responseHeaders, true,
SystemClock.elapsedRealtime() - requestStart);
}
// A HTTP 304 response does not have all header fields. We
// have to use the header fields from the cache entry plus
// the new ones from the response.
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5
entry.responseHeaders.putAll(responseHeaders); //如果不空 那么就添加頭 然后返回 數(shù)據(jù)了
return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, entry.data,
entry.responseHeaders, true,
SystemClock.elapsedRealtime() - requestStart);
}
// Some responses such as 204s do not have content. We must check.
if (httpResponse.getEntity() != null) { //不是304的情況
responseContents = entityToBytes(httpResponse.getEntity()); //獲取響應(yīng)的內(nèi)容 下面返回響應(yīng)即可
} 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, statusLine);
if (statusCode < 200 || statusCode > 299) {
throw new IOException();
}
return new NetworkResponse(statusCode, responseContents, responseHeaders, false,
SystemClock.elapsedRealtime() - requestStart);
} catch (SocketTimeoutException e) {
attemptRetryOnException("socket", request, new TimeoutError());
} catch (ConnectTimeoutException e) {
attemptRetryOnException("connection", request, new TimeoutError());
} catch (MalformedURLException e) {
throw new RuntimeException("Bad URL " + request.getUrl(), e);
} catch (IOException e) {
int statusCode = 0;
NetworkResponse networkResponse = null;
if (httpResponse != null) {
statusCode = httpResponse.getStatusLine().getStatusCode();
} else {
throw new NoConnectionError(e);
}
VolleyLog.e("Unexpected response code %d for %s", statusCode, request.getUrl());
if (responseContents != null) {
networkResponse = new NetworkResponse(statusCode, responseContents,
responseHeaders, false, SystemClock.elapsedRealtime() - requestStart);
if (statusCode == HttpStatus.SC_UNAUTHORIZED ||
statusCode == HttpStatus.SC_FORBIDDEN) {
attemptRetryOnException("auth",
request, new AuthFailureError(networkResponse));
} else {
// TODO: Only throw ServerError for 5xx status codes.
throw new ServerError(networkResponse);
}
} else {
throw new NetworkError(networkResponse);
}
}
}
然后看 HttpStack的 請(qǐng)求代碼:
@Override
public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)
throws IOException, AuthFailureError {
String url = request.getUrl();
HashMap<String, String> map = new HashMap<String, String>();
map.putAll(request.getHeaders()); //添加請(qǐng)求頭
map.putAll(additionalHeaders);
if (mUrlRewriter != null) {
String rewritten = mUrlRewriter.rewriteUrl(url);
if (rewritten == null) {
throw new IOException("URL blocked by rewriter: " + url);
}
url = rewritten;
}
URL parsedUrl = new URL(url);
HttpURLConnection connection = openConnection(parsedUrl, request); //打開(kāi)連接
for (String headerName : map.keySet()) { //設(shè)置頭
connection.addRequestProperty(headerName, map.get(headerName));
}
setConnectionParametersForRequest(connection, request); //在這個(gè)函數(shù)里添加請(qǐng)求的參數(shù) 和一些基本的信息配置
// Initialize HttpResponse with data from the HttpURLConnection.
ProtocolVersion protocolVersion = new ProtocolVersion("HTTP", 1, 1);
int responseCode = connection.getResponseCode(); //下面就是些獲取響應(yīng)信息后的處理了
if (responseCode == -1) {
// -1 is returned by getResponseCode() if the response code could not be retrieved.
// Signal to the caller that something was wrong with the connection.
throw new IOException("Could not retrieve response code from HttpUrlConnection.");
}
StatusLine responseStatus = new BasicStatusLine(protocolVersion,
connection.getResponseCode(), connection.getResponseMessage());
BasicHttpResponse response = new BasicHttpResponse(responseStatus);
response.setEntity(entityFromConnection(connection));
for (Entry<String, List<String>> header : connection.getHeaderFields().entrySet()) {
if (header.getKey() != null) {
Header h = new BasicHeader(header.getKey(), header.getValue().get(0));
response.addHeader(h);
}
}
return response;
}
這個(gè)函數(shù)中主要是HttpUrlConnection的使用 添加頭在 connection.addRequestProperty方法中 添加參數(shù)需要獲取流 然后寫(xiě)入?yún)?shù) 下面這個(gè)函數(shù)中有介紹 假設(shè)是post方式:
case Method.POST:
connection.setRequestMethod("POST");
addBodyIfExists(connection, request);
break;
private static void addBodyIfExists(HttpURLConnection connection, Request<?> request)
throws IOException, AuthFailureError {
byte[] body = request.getBody();
if (body != null) {
connection.setDoOutput(true);
connection.addRequestProperty(HEADER_CONTENT_TYPE, request.getBodyContentType());
DataOutputStream out = new DataOutputStream(connection.getOutputStream());
out.write(body);
out.close();
}
}
將body寫(xiě)入到流中 就可以 參數(shù)的封裝在 body中
public byte[] getBody() throws AuthFailureError {
Map<String, String> params = getParams();
if (params != null && params.size() > 0) {
return encodeParameters(params, getParamsEncoding());
}
return null;
}
getParams方法 是Request需要重寫(xiě)的一個(gè)方法 返回值就是參數(shù)的Map集合
[java] view plain copy 在CODE上查看代碼片派生到我的代碼片
private byte[] encodeParameters(Map<String, String> params, String paramsEncoding) {
StringBuilder encodedParams = new StringBuilder();
try {
for (Map.Entry<String, String> entry : params.entrySet()) {
encodedParams.append(URLEncoder.encode(entry.getKey(), paramsEncoding));
encodedParams.append('=');
encodedParams.append(URLEncoder.encode(entry.getValue(), paramsEncoding));
encodedParams.append('&');
}
return encodedParams.toString().getBytes(paramsEncoding);
} catch (UnsupportedEncodingException uee) {
throw new RuntimeException("Encoding not supported: " + paramsEncoding, uee);
}
}
這個(gè)函數(shù)就是按照一定規(guī)則拼接字符串參數(shù)即可 然后 就可以提交參數(shù)了
最后介紹下這個(gè)框架主要的幾個(gè)類(lèi)、成員及他們作用:
RequestQueue 用來(lái)處理請(qǐng)求的隊(duì)列,請(qǐng)求都放在這個(gè)類(lèi)中 調(diào)用start方法 開(kāi)始處理請(qǐng)求
mCache 請(qǐng)求的緩存,當(dāng)提交了一個(gè)請(qǐng)求 并且此請(qǐng)求需要緩存時(shí),會(huì)放入這個(gè)緩存中
mNetwork 單純用于提交網(wǎng)絡(luò)請(qǐng)求的接口 只有一個(gè)提交請(qǐng)求的方法 需要傳入一個(gè)HttpStack來(lái)完成請(qǐng)求的提交
mDelivery 用于請(qǐng)求響應(yīng)后的 接口回調(diào)等功能
mDispatchers NetWork調(diào)度器線程數(shù)組 包含4個(gè)對(duì)象處理請(qǐng)求 目的是為了提高效率 當(dāng)沒(méi)有緩存可以獲取或者已經(jīng)過(guò)期 需要刷新時(shí) 會(huì)調(diào)用這個(gè)線程的run方法 如果沒(méi)有 則阻塞
mCacheDispatcher 緩存調(diào)度器線程 處理已經(jīng)緩存了的請(qǐng)求 如果沒(méi)有緩存 則將請(qǐng)求放入 NetWorkQueue 等待調(diào)用
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家學(xué)習(xí)Android Volley框架有所幫助。
- Android 中Volley二次封裝并實(shí)現(xiàn)網(wǎng)絡(luò)請(qǐng)求緩存
- Android中volley封裝實(shí)踐記錄
- Android Volley框架全面解析
- Android Volley框架使用方法詳解
- Android的HTTP類(lèi)庫(kù)Volley入門(mén)學(xué)習(xí)教程
- Android中Volley框架下保持會(huì)話方法
- Android 開(kāi)發(fā)中Volley詳解及實(shí)例
- android 網(wǎng)絡(luò)請(qǐng)求庫(kù)volley方法詳解
- Android 網(wǎng)絡(luò)請(qǐng)求框架Volley實(shí)例詳解
- Android中volley封裝實(shí)踐記錄(二)
相關(guān)文章
Android getSystemService用法實(shí)例總結(jié)
這篇文章主要介紹了Android getSystemService用法,結(jié)合實(shí)例形式總結(jié)分析了getSystemService獲取系統(tǒng)Service的相關(guān)使用方法與注意事項(xiàng),需要的朋友可以參考下2016-01-01
Android使用個(gè)推實(shí)現(xiàn)三方應(yīng)用的推送功能
這篇文章主要為大家詳細(xì)介紹了Android使用個(gè)推實(shí)現(xiàn)三方應(yīng)用的推送功能,感興趣的小伙伴們可以參考一下2016-08-08
詳解如何從原生Android 跳轉(zhuǎn)到hbuilder項(xiàng)目
這篇文章主要介紹了從原生Android 跳轉(zhuǎn)到hbuilder項(xiàng)目,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-08-08
Android仿蘋(píng)果關(guān)機(jī)界面實(shí)現(xiàn)代碼
這篇文章主要為大家詳細(xì)介紹了Android仿蘋(píng)果關(guān)機(jī)界面的實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09
Flutter?日歷組件簡(jiǎn)單實(shí)現(xiàn)
這篇文章主要為大家介紹了Flutter?日歷組件簡(jiǎn)單實(shí)現(xiàn)的圖文示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
Android 使用版本控制工具時(shí)添加忽略文件的方式(詳解)
下面小編就為大家?guī)?lái)一篇Android 使用版本控制工具時(shí)添加忽略文件的方式(詳解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-01-01
Android 基于RecyclerView實(shí)現(xiàn)的歌詞滾動(dòng)自定義控件
這篇文章主要介紹了Android 基于RecyclerView實(shí)現(xiàn)的歌詞滾動(dòng)自定義控件,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03

