Äú¿ÉÒÔ¾èÖú£¬Ö§³ÖÎÒÃǵĹ«ÒæÊÂÒµ¡£

1Ôª 10Ôª 50Ôª





ÈÏÖ¤Â룺  ÑéÖ¤Âë,¿´²»Çå³þ?Çëµã»÷Ë¢ÐÂÑéÖ¤Âë ±ØÌî



  ÇóÖª ÎÄÕ ÎÄ¿â Lib ÊÓÆµ iPerson ¿Î³Ì ÈÏÖ¤ ×Éѯ ¹¤¾ß ½²×ù Modeler   Code  
»áÔ±   
 
   
 
 
     
   
 ¶©ÔÄ
  ¾èÖú
Android VolleyÍêÈ«½âÎö(ËÄ)£¬´øÄã´ÓÔ´ÂëµÄ½Ç¶ÈÀí½âVolley
 
×÷Õß guolinµÄ²©¿Í£¬»ðÁú¹ûÈí¼þ    ·¢²¼ÓÚ 2014-07-21
  4922  次浏览      28
 

¾­¹ýǰÈýƪÎÄÕµÄѧϰ£¬VolleyµÄÓ÷¨ÎÒÃÇÒѾ­ÕÆÎյIJ¶àÁË£¬µ«ÊǶÔÓÚVolleyµÄ¹¤×÷Ô­Àí£¬¿ÖÅÂÓкܶàÅóÓÑ»¹²»ÊǺÜÇå³þ¡£Òò´Ë£¬±¾ÆªÎÄÕÂÖÐÎÒÃǾÍÀ´Ò»ÆðÔĶÁÒ»ÏÂVolleyµÄÔ´Â룬½«ËüµÄ¹¤×÷Á÷³ÌÕûÌ嵨ÊáÀíÒ»±é¡£Í¬Ê±£¬ÕâÒ²ÊÇVolleyϵÁеÄ×îºóһƪÎÄÕÂÁË¡£

Æäʵ£¬VolleyµÄ¹Ù·½ÎĵµÖб¾Éí¾Í¸½ÓÐÁËÒ»ÕÅVolleyµÄ¹¤×÷Á÷³Ìͼ£¬ÈçÏÂͼËùʾ¡£

¶àÊýÅóÓÑͻȻ¿´µ½Ò»ÕÅÕâÑùµÄͼ£¬Ó¦¸Ã»áºÍÎÒÒ»Ñù£¬¸Ð¾õһͷÎíË®°É£¿Ã»´í£¬Ä¿Ç°ÎÒÃǶÔVolley±³ºóµÄ¹¤×÷Ô­Àí»¹Ã»ÓÐÒ»¸ö¸ÅÄîÐÔµÄÀí½â£¬Ö±½Ó¾ÍÀ´¿´ÕâÕÅͼ×ÔÈ»»áÓÐЩ³ÔÁ¦¡£²»¹ýû¹ØÏµ£¬ÏÂÃæÎÒÃǾÍÈ¥·ÖÎöÒ»ÏÂVolleyµÄÔ´Â룬֮ºóÔÙÖØÐÂÀ´¿´ÕâÕÅͼ¾Í»áºÃÀí½â¶àÁË¡£

˵Æð·ÖÎöÔ´Â룬ÄÇôӦ¸Ã´ÓÄĶù¿ªÊ¼¿´ÆðÄØ£¿Õâ¾ÍÒª»Ø¹ËÒ»ÏÂVolleyµÄÓ÷¨ÁË£¬»¹¼ÇµÃÂð£¬Ê¹ÓÃVolleyµÄµÚÒ»²½£¬Ê×ÏÈÒªµ÷ÓÃVolley.newRequestQueue(context)·½·¨À´»ñȡһ¸öRequestQueue¶ÔÏó£¬ÄÇôÎÒÃÇ×ÔȻҪ´ÓÕâ¸ö·½·¨¿ªÊ¼¿´ÆðÁË£¬´úÂëÈçÏÂËùʾ£º

public static RequestQueue newRequestQueue(Context context) {  
return newRequestQueue(context, null);
}

Õâ¸ö·½·¨½ö½öÖ»ÓÐÒ»ÐдúÂ룬ֻÊǵ÷ÓÃÁËnewRequestQueue()µÄ·½·¨ÖØÔØ£¬²¢¸øµÚ¶þ¸ö²ÎÊý´«Èënull¡£ÄÇÎÒÃÇ¿´Ï´øÓÐÁ½¸ö²ÎÊýµÄnewRequestQueue()·½·¨ÖеĴúÂ룬ÈçÏÂËùʾ£º

public static RequestQueue newRequestQueue(Context context, HttpStack stack) {  
File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);
String userAgent = "volley/0";
try {
String packageName = context.getPackageName();
PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
userAgent = packageName + "/" + info.versionCode;
} catch (NameNotFoundException e) {
}
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;
}

¿ÉÒÔ¿´µ½£¬ÕâÀïÔÚµÚ10ÐÐÅжÏÈç¹ûstackÊǵÈÓÚnullµÄ£¬ÔòÈ¥´´½¨Ò»¸öHttpStack¶ÔÏó£¬ÕâÀï»áÅжÏÈç¹ûÊÖ»úϵͳ°æ±¾ºÅÊÇ´óÓÚ9µÄ£¬Ôò´´½¨Ò»¸öHurlStackµÄʵÀý£¬·ñÔò¾Í´´½¨Ò»¸öHttpClientStackµÄʵÀý¡£Êµ¼ÊÉÏHurlStackµÄÄÚ²¿¾ÍÊÇʹÓÃHttpURLConnection½øÐÐÍøÂçͨѶµÄ£¬¶øHttpClientStackµÄÄÚ²¿ÔòÊÇʹÓÃHttpClient½øÐÐÍøÂçͨѶµÄ£¬ÕâÀïΪʲôÕâÑùÑ¡ÔñÄØ£¿¿ÉÒԲο¼ÎÒ֮ǰ·­ÒëµÄһƪÎÄÕÂAndroid·ÃÎÊÍøÂ磬ʹÓÃHttpURLConnection»¹ÊÇHttpClient£¿

´´½¨ºÃÁËHttpStackÖ®ºó£¬½ÓÏÂÀ´ÓÖ´´½¨ÁËÒ»¸öNetwork¶ÔÏó£¬ËüÊÇÓÃÓÚ¸ù¾Ý´«ÈëµÄHttpStack¶ÔÏóÀ´´¦ÀíÍøÂçÇëÇóµÄ£¬½ô½Ó×Ånew³öÒ»¸öRequestQueue¶ÔÏ󣬲¢µ÷ÓÃËüµÄstart()·½·¨½øÐÐÆô¶¯£¬È»ºó½«RequestQueue·µ»Ø£¬ÕâÑùnewRequestQueue()µÄ·½·¨¾ÍÖ´ÐнáÊøÁË¡£

ÄÇôRequestQueueµÄ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µÄʵÀý£¬È»ºóµ÷ÓÃÁËËüµÄstart()·½·¨£¬½Ó×ÅÔÚÒ»¸öforÑ­»·ÀïÈ¥´´½¨NetworkDispatcherµÄʵÀý£¬²¢·Ö±ðµ÷ÓÃËüÃǵÄstart()·½·¨¡£ÕâÀïµÄCacheDispatcherºÍNetworkDispatcher¶¼ÊǼ̳Ð×ÔThreadµÄ£¬¶øÄ¬ÈÏÇé¿öÏÂforÑ­»·»áÖ´ÐÐËĴΣ¬Ò²¾ÍÊÇ˵µ±µ÷ÓÃÁËVolley.newRequestQueue(context)Ö®ºó£¬¾Í»áÓÐÎå¸öÏß³ÌÒ»Ö±ÔÚºǫ́ÔËÐУ¬²»¶ÏµÈ´ýÍøÂçÇëÇóµÄµ½À´£¬ÆäÖÐCacheDispatcherÊÇ»º´æỊ̈߳¬NetworkDispatcherÊÇÍøÂçÇëÇóÏ̡߳£

µÃµ½ÁËRequestQueueÖ®ºó£¬ÎÒÃÇÖ»ÐèÒª¹¹½¨³öÏàÓ¦µÄRequest£¬È»ºóµ÷ÓÃRequestQueueµÄadd()·½·¨½«Request´«Èë¾Í¿ÉÒÔÍê³ÉÍøÂçÇëÇó²Ù×÷ÁË£¬ÄÇô²»ÓÃ˵£¬add()·½·¨µÄÄÚ²¿¿Ï¶¨ÓÐ×ŷdz£¸´ÔÓµÄÂß¼­£¬ÎÒÃÇÀ´Ò»Æð¿´Ò»Ï£º

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.
request.setSequence(getSequenceNumber());
request.addMarker("add-to-queue");
// If the request is uncacheable, skip the cache queue and go straight to the network.
if (!request.shouldCache()) {
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)) {
// 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 {
// Insert 'null' queue for this cacheKey, indicating there is now a request in
// flight.
mWaitingRequests.put(cacheKey, null);
mCacheQueue.add(request);
}
return request;
}
}

¿ÉÒÔ¿´µ½£¬ÔÚµÚ11ÐеÄʱºò»áÅжϵ±Ç°µÄÇëÇóÊÇ·ñ¿ÉÒÔ»º´æ£¬Èç¹û²»ÄÜ»º´æÔòÔÚµÚ12ÐÐÖ±½Ó½«ÕâÌõÇëÇó¼ÓÈëÍøÂçÇëÇó¶ÓÁУ¬¿ÉÒÔ»º´æµÄ»°ÔòÔÚµÚ33Ðн«ÕâÌõÇëÇó¼ÓÈ뻺´æ¶ÓÁС£ÔÚĬÈÏÇé¿öÏ£¬Ã¿ÌõÇëÇó¶¼ÊÇ¿ÉÒÔ»º´æµÄ£¬µ±È»ÎÒÃÇÒ²¿ÉÒÔµ÷ÓÃRequestµÄsetShouldCache(false)·½·¨À´¸Ä±äÕâһĬÈÏÐÐΪ¡£

OK£¬ÄÇô¼ÈȻĬÈÏÿÌõÇëÇó¶¼ÊÇ¿ÉÒÔ»º´æµÄ£¬×ÔÈ»¾Í±»Ìí¼Óµ½ÁË»º´æ¶ÓÁÐÖУ¬ÓÚÊÇÒ»Ö±ÔÚºǫ́µÈ´ýµÄ»º´æÏ߳̾ÍÒª¿ªÊ¼ÔËÐÐÆðÀ´ÁË£¬ÎÒÃÇ¿´ÏÂCacheDispatcherÖеÄrun()·½·¨£¬´úÂëÈçÏÂËùʾ£º

public class CacheDispatcher extends Thread {  

¡­¡­

@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 {
// Get a request from the cache triage queue, blocking until
// at least one is available.
final Request<?> request = mCacheQueue.take();
request.addMarker("cache-queue-take");
// 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) {
request.addMarker("cache-miss");
// Cache miss; send off to the network dispatcher.
mNetworkQueue.put(request);
continue;
}
// If it is completely expired, just send it to the network.
if (entry.isExpired()) {
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");
Response<?> response = request.parseNetworkResponse(
new NetworkResponse(entry.data, entry.responseHeaders));
request.addMarker("cache-hit-parsed");
if (!entry.refreshNeeded()) {
// Completely unexpired cache hit. Just deliver the response.
mDelivery.postResponse(request, response);
} else {
// 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;
}
}
}
}

´úÂëÓе㳤£¬ÎÒÃÇÖ»ÌôÖØµã¿´¡£Ê×ÏÈÔÚ11ÐпÉÒÔ¿´µ½Ò»¸öwhile(true)Ñ­»·£¬ËµÃ÷»º´æÏß³ÌʼÖÕÊÇÔÚÔËÐе쬽Ó×ÅÔÚµÚ23Ðл᳢ÊÔ´Ó»º´æµ±ÖÐÈ¡³öÏìÓ¦½á¹û£¬ÈçºÎΪ¿ÕµÄ»°Ôò°ÑÕâÌõÇëÇó¼ÓÈëµ½ÍøÂçÇëÇó¶ÓÁÐÖУ¬Èç¹û²»Îª¿ÕµÄ»°ÔÙÅжϸûº´æÊÇ·ñÒѹýÆÚ£¬Èç¹ûÒѾ­¹ýÆÚÁËÔòͬÑù°ÑÕâÌõÇëÇó¼ÓÈëµ½ÍøÂçÇëÇó¶ÓÁÐÖУ¬·ñÔò¾ÍÈÏΪ²»ÐèÒªÖØ·¢ÍøÂçÇëÇó£¬Ö±½ÓʹÓûº´æÖеÄÊý¾Ý¼´¿É¡£Ö®ºó»áÔÚµÚ39Ðе÷ÓÃRequestµÄparseNetworkResponse()·½·¨À´¶ÔÊý¾Ý½øÐнâÎö£¬ÔÙÍùºó¾ÍÊǽ«½âÎö³öÀ´µÄÊý¾Ý½øÐлص÷ÁË£¬Õⲿ·Ö´úÂëÎÒÃÇÏÈÌø¹ý£¬ÒòΪËüµÄÂß¼­ºÍNetworkDispatcherºó°ë²¿·ÖµÄÂß¼­ÊÇ»ù±¾ÏàͬµÄ£¬ÄÇôÎÒÃǵÈϺϲ¢ÔÚÒ»Æð¿´¾ÍºÃÁË£¬ÏÈÀ´¿´Ò»ÏÂNetworkDispatcherÖÐÊÇÔõô´¦ÀíÍøÂçÇëÇó¶ÓÁе쬴úÂëÈçÏÂËùʾ£º

public class NetworkDispatcher extends Thread {  
¡­¡­
@Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Request<?> request;
while (true) {
try {
// Take a request from the queue.
request = mQueue.take();
} 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);
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);
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) {
mCache.put(request.getCacheKey(), response.cacheEntry);
request.addMarker("network-cache-written");
}
// Post the response back.
request.markDelivered();
mDelivery.postResponse(request, response);
} catch (VolleyError volleyError) {
parseAndDeliverNetworkError(request, volleyError);
} catch (Exception e) {
VolleyLog.e(e, "Unhandled exception %s", e.toString());
mDelivery.postError(request, new VolleyError(e));
}
}
}
}

ͬÑùµØ£¬ÔÚµÚ7ÐÐÎÒÃÇ¿´µ½ÁËÀàËÆµÄwhile(true)Ñ­»·£¬ËµÃ÷ÍøÂçÇëÇóÏß³ÌÒ²ÊÇÔÚ²»¶ÏÔËÐеġ£ÔÚµÚ28ÐеÄʱºò»áµ÷ÓÃNetworkµÄperformRequest()·½·¨À´È¥·¢ËÍÍøÂçÇëÇ󣬶øNetworkÊÇÒ»¸ö½Ó¿Ú£¬ÕâÀï¾ßÌåµÄʵÏÖÊÇBasicNetwork£¬ÎÒÃÇÀ´¿´ÏÂËüµÄperformRequest()·½·¨£¬ÈçÏÂËùʾ£º

public class BasicNetwork implements Network {  
¡­¡­
@Override
public NetworkResponse performRequest(Request<?> request) throws VolleyError {
long requestStart = SystemClock.elapsedRealtime();
while (true) {
HttpResponse httpResponse = null;
byte[] responseContents = null;
Map<String, String> responseHeaders = new HashMap<String, String>();
try {
// Gather headers.
Map<String, String> headers = new HashMap<String, String>();
addCacheHeaders(headers, request.getCacheEntry());
httpResponse = mHttpStack.performRequest(request, headers);
StatusLine statusLine = httpResponse.getStatusLine();
int statusCode = statusLine.getStatusCode();
responseHeaders = convertHeaders(httpResponse.getAllHeaders());
// Handle cache validation.
if (statusCode == HttpStatus.SC_NOT_MODIFIED) {
return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED,
request.getCacheEntry() == null ? null : request.getCacheEntry().data,
responseHeaders, true);
}
// Some responses such as 204s do not have content. We must check.
if (httpResponse.getEntity() != null) {
responseContents = entityToBytes(httpResponse.getEntity());
} 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);
} catch (Exception e) {
¡­¡­
}
}
}
}

Õâ¶Î·½·¨Öдó¶à¶¼ÊÇÒ»Ð©ÍøÂçÇëÇóϸ½Ú·½ÃæµÄ¶«Î÷£¬ÎÒÃDz¢²»ÐèҪ̫¶à¹ØÐÄ£¬ÐèҪעÒâµÄÊÇÔÚµÚ14Ðе÷ÓÃÁËHttpStackµÄperformRequest()·½·¨£¬ÕâÀïµÄHttpStack¾ÍÊÇÔÚÒ»¿ªÊ¼µ÷ÓÃnewRequestQueue()·½·¨ÊÇ´´½¨µÄʵÀý£¬Ä¬ÈÏÇé¿öÏÂÈç¹ûϵͳ°æ±¾ºÅ´óÓÚ9¾Í´´½¨µÄHurlStack¶ÔÏ󣬷ñÔò´´½¨HttpClientStack¶ÔÏó¡£Ç°ÃæÒѾ­Ëµ¹ý£¬ÕâÁ½¸ö¶ÔÏóµÄÄÚ²¿Êµ¼Ê¾ÍÊÇ·Ö±ðʹÓÃHttpURLConnectionºÍHttpClientÀ´·¢ËÍÍøÂçÇëÇóµÄ£¬ÎÒÃǾͲ»ÔÙ¸ú½øÈ¥ÔĶÁÁË£¬Ö®ºó»á½«·þÎñÆ÷·µ»ØµÄÊý¾Ý×é×°³ÉÒ»¸öNetworkResponse¶ÔÏó½øÐзµ»Ø¡£

ÔÚNetworkDispatcherÖÐÊÕµ½ÁËNetworkResponseÕâ¸ö·µ»ØÖµºóÓÖ»áµ÷ÓÃRequestµÄparseNetworkResponse()·½·¨À´½âÎöNetworkResponseÖеÄÊý¾Ý£¬ÒÔ¼°½«Êý¾ÝдÈëµ½»º´æ£¬Õâ¸ö·½·¨µÄʵÏÖÊǽ»¸øRequestµÄ×ÓÀàÀ´Íê³ÉµÄ£¬ÒòΪ²»Í¬ÖÖÀàµÄRequest½âÎöµÄ·½Ê½Ò²¿Ï¶¨²»Í¬¡£»¹¼ÇµÃÎÒÃÇÔÚÉÏһƪÎÄÕÂÖÐѧϰµÄ×Ô¶¨ÒåRequestµÄ·½Ê½Âð£¿ÆäÖÐparseNetworkResponse()Õâ¸ö·½·¨¾ÍÊDZØÐëÒªÖØÐ´µÄ¡£

ÔÚ½âÎöÍêÁËNetworkResponseÖеÄÊý¾ÝÖ®ºó£¬ÓÖ»áµ÷ÓÃExecutorDeliveryµÄpostResponse()·½·¨À´»Øµ÷½âÎö³öµÄÊý¾Ý£¬´úÂëÈçÏÂËùʾ£º

public void postResponse(Request<?> request, Response<?> response, Runnable runnable) {  
request.markDelivered();
request.addMarker("post-response");
mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, runnable));
}

ÆäÖУ¬ÔÚmResponsePosterµÄexecute()·½·¨Öд«ÈëÁËÒ»¸öResponseDeliveryRunnable¶ÔÏ󣬾ͿÉÒÔ±£Ö¤¸Ã¶ÔÏóÖеÄrun()·½·¨¾ÍÊÇÔÚÖ÷Ï̵߳±ÖÐÔËÐеÄÁË£¬ÎÒÃÇ¿´ÏÂrun()·½·¨ÖеĴúÂëÊÇʲôÑùµÄ£º

private class ResponseDeliveryRunnable implements Runnable {  
private final Request mRequest;
private final Response mResponse;
private final Runnable mRunnable;

public ResponseDeliveryRunnable(Request request, Response response, Runnable runnable) {
mRequest = request;
mResponse = response;
mRunnable = runnable;
}

@SuppressWarnings("unchecked")
@Override
public void run() {
// If this request has canceled, finish it and don't deliver.
if (mRequest.isCanceled()) {
mRequest.finish("canceled-at-delivery");
return;
}
// Deliver a normal response or error, depending.
if (mResponse.isSuccess()) {
mRequest.deliverResponse(mResponse.result);
} else {
mRequest.deliverError(mResponse.error);
}
// If this is an intermediate response, add a marker, otherwise we're done
// and the request can be finished.
if (mResponse.intermediate) {
mRequest.addMarker("intermediate-response");
} else {
mRequest.finish("done");
}
// If we have been provided a post-delivery runnable, run it.
if (mRunnable != null) {
mRunnable.run();
}
}
}

´úÂëËäÈ»²»¶à£¬µ«ÎÒÃDz¢²»ÐèÒªÐÐÐÐÔĶÁ£¬×¥×¡Öص㿴¼´¿É¡£ÆäÖÐÔÚµÚ22Ðе÷ÓÃÁËRequestµÄdeliverResponse()·½·¨£¬ÓÐûÓиоõºÜÊìϤ£¿Ã»´í£¬Õâ¸ö¾ÍÊÇÎÒÃÇÔÚ×Ô¶¨ÒåRequestʱÐèÒªÖØÐ´µÄÁíÍâÒ»¸ö·½·¨£¬Ã¿Ò»ÌõÍøÂçÇëÇóµÄÏìÓ¦¶¼Êǻص÷µ½Õâ¸ö·½·¨ÖУ¬×îºóÎÒÃÇÔÙÔÚÕâ¸ö·½·¨Öн«ÏìÓ¦µÄÊý¾Ý»Øµ÷µ½Response.ListenerµÄonResponse()·½·¨ÖоͿÉÒÔÁË¡£

ºÃÁË£¬µ½ÕâÀïÎÒÃǾͰÑVolleyµÄÍêÕûÖ´ÐÐÁ÷³ÌÈ«²¿ÊáÀíÁËÒ»±é£¬ÄãÊDz»ÊÇÒѾ­¸Ð¾õÒѾ­ºÜÇåÎúÁËÄØ£¿¶ÔÁË£¬»¹¼ÇµÃÔÚÎÄÕÂÒ»¿ªÊ¼µÄÄÇÕÅÁ÷³ÌͼÂ𣬸ղݹ²»ÄÜÀí½â£¬ÏÖÔÚÎÒÃÇÔÙÀ´ÖØÐ¿´ÏÂÕâÕÅͼ£º

ÆäÖÐÀ¶É«²¿·Ö´ú±íÖ÷Ị̈߳¬ÂÌÉ«²¿·Ö´ú±í»º´æỊ̈߳¬³ÈÉ«²¿·Ö´ú±íÍøÂçÏ̡߳£ÎÒÃÇÔÚÖ÷Ïß³ÌÖе÷ÓÃRequestQueueµÄadd()·½·¨À´Ìí¼ÓÒ»ÌõÍøÂçÇëÇó£¬ÕâÌõÇëÇó»áÏȱ»¼ÓÈëµ½»º´æ¶ÓÁе±ÖУ¬Èç¹û·¢ÏÖ¿ÉÒÔÕÒµ½ÏàÓ¦µÄ»º´æ½á¹û¾ÍÖ±½Ó¶ÁÈ¡»º´æ²¢½âÎö£¬È»ºó»Øµ÷¸øÖ÷Ï̡߳£Èç¹ûÔÚ»º´æÖÐûÓÐÕÒµ½½á¹û£¬Ôò½«ÕâÌõÇëÇó¼ÓÈëµ½ÍøÂçÇëÇó¶ÓÁÐÖУ¬È»ºó´¦Àí·¢ËÍHTTPÇëÇ󣬽âÎöÏìÓ¦½á¹û£¬Ð´È뻺´æ£¬²¢»Øµ÷Ö÷Ï̡߳£

   
4922 ´Îä¯ÀÀ       28
 
Ïà¹ØÎÄÕÂ

ÊÖ»úÈí¼þ²âÊÔÓÃÀýÉè¼ÆÊµ¼ù
ÊÖ»ú¿Í»§¶ËUI²âÊÔ·ÖÎö
iPhoneÏûÏ¢ÍÆËÍ»úÖÆÊµÏÖÓë̽ÌÖ
AndroidÊÖ»ú¿ª·¢£¨Ò»£©
 
Ïà¹ØÎĵµ

Android_UI¹Ù·½Éè¼Æ½Ì³Ì
ÊÖ»ú¿ª·¢Æ½Ì¨½éÉÜ
androidÅÄÕÕ¼°ÉÏ´«¹¦ÄÜ
Android½²ÒåÖÇÄÜÊÖ»ú¿ª·¢
Ïà¹Ø¿Î³Ì

Android¸ß¼¶Òƶ¯Ó¦ÓóÌÐò
Androidϵͳ¿ª·¢
AndroidÓ¦Óÿª·¢
ÊÖ»úÈí¼þ²âÊÔ
×îл¼Æ»®
DeepSeekÔÚÈí¼þ²âÊÔÓ¦ÓÃʵ¼ù 4-12[ÔÚÏß]
DeepSeek´óÄ£ÐÍÓ¦Óÿª·¢Êµ¼ù 4-19[ÔÚÏß]
UAF¼Ü¹¹ÌåϵÓëʵ¼ù 4-11[±±¾©]
AIÖÇÄÜ»¯Èí¼þ²âÊÔ·½·¨Óëʵ¼ù 5-23[ÉϺ£]
»ùÓÚ UML ºÍEA½øÐзÖÎöÉè¼Æ 4-26[±±¾©]
ÒµÎñ¼Ü¹¹Éè¼ÆÓ뽨ģ 4-18[±±¾©]

androidÈË»ú½çÃæÖ¸ÄÏ
AndroidÊÖ»ú¿ª·¢£¨Ò»£©
AndroidÊÖ»ú¿ª·¢£¨¶þ£©
AndroidÊÖ»ú¿ª·¢£¨Èý£©
AndroidÊÖ»ú¿ª·¢£¨ËÄ£©
iPhoneÏûÏ¢ÍÆËÍ»úÖÆÊµÏÖ̽ÌÖ
ÊÖ»úÈí¼þ²âÊÔÓÃÀýÉè¼ÆÊµ¼ù
ÊÖ»ú¿Í»§¶ËUI²âÊÔ·ÖÎö
ÊÖ»úÈí¼þ×Ô¶¯»¯²âÊÔÑо¿±¨¸æ


Android¸ß¼¶Òƶ¯Ó¦ÓóÌÐò
AndroidÓ¦Óÿª·¢
Androidϵͳ¿ª·¢
ÊÖ»úÈí¼þ²âÊÔ
ǶÈëʽÈí¼þ²âÊÔ
AndroidÈí¡¢Ó²¡¢ÔÆÕûºÏ


ÁìÏÈIT¹«Ë¾ android¿ª·¢Æ½Ì¨×î¼Ñʵ¼ù
±±¾© Android¿ª·¢¼¼Êõ½ø½×
ijÐÂÄÜÔ´ÁìÓòÆóÒµ Android¿ª·¢¼¼Êõ
ijº½Ì칫˾ Android¡¢IOSÓ¦ÓÃÈí¼þ¿ª·¢
°¢¶û¿¨ÌØ LinuxÄÚºËÇý¶¯
°¬Ä¬Éú ǶÈëʽÈí¼þ¼Ü¹¹Éè¼Æ
Î÷ÃÅ×Ó Ç¶Èëʽ¼Ü¹¹Éè¼Æ