public Request Add(Request request) { request.SetRequestQueue(this); //添加到当前请求列表中 lock (mCurrentRequests) { mCurrentRequests.Add(request); } request.Sequence = GetSequenceNumber(); request.AddMarker("add-to-queue"); //如果请求不需要缓存则直接加入到网络请求队列中 if (!request.ShouldCache()) { mNetworkQueue.Enqueue(request); return(request); } /* * 先将请求加入到缓存请求队列中,并且将后面的重复请求 * 添加到mWaitingRequests中,目的是当第一个请求完成后 * 后面重复的请求直接添加到缓存请求队列中,避免重复对 * 网络进行请求 */ lock (mWaitingRequests) { String cacheKey = request.GetCacheKey(); if (mWaitingRequests.ContainsKey(cacheKey)) { Queue <Request> stagedRequests = null; mWaitingRequests.TryGetValue(cacheKey, out stagedRequests); if (stagedRequests == null) { stagedRequests = new Queue <Request>(); } stagedRequests.Enqueue(request); if (VolleyLog.DEBUG) { VolleyLog.V("Request for cacheKey={0} is in flight,putting on hold.", cacheKey); } } else { mWaitingRequests.Add(cacheKey, null); mCacheQueue.Enqueue(request); } return(request); } }
/// <summary> /// 当需要的空间大于指定空间后清除部分缓存 /// </summary> private void PruneIfNeeded(int neededSpace) { if (mTotalSize + neededSpace < mMaxCacheSizeInBytes) { return; } if (VolleyLog.DEBUG) { VolleyLog.V("Pruning old cache entries."); } long before = mTotalSize; int prunedFiles = 0; long startTime = SystemClock.ElapsedRealtime(); Dictionary <string, CacheHeader> delDic = new Dictionary <string, CacheHeader>(); foreach (KeyValuePair <String, CacheHeader> pair in mEntries) { CacheHeader e = pair.Value; var fi = GetFileForKey(e.Key); fi.Delete(); if (!File.Exists(fi.FullName)) { mTotalSize -= e.Size; } else { VolleyLog.D("Could not delete cache entry for key={0},filename={1}", e.Key, GetFilenameForKey(e.Key)); } prunedFiles++; delDic.Add(pair.Key, pair.Value); if (mTotalSize + neededSpace < mMaxCacheSizeInBytes * HYSTERESIS_FACTOR) { break; } } foreach (KeyValuePair <string, CacheHeader> del in delDic) { mEntries.Remove(del.Key); } if (VolleyLog.DEBUG) { VolleyLog.V("Pruned {0} files,{1} bytes,{2} ms", prunedFiles, (mTotalSize - before), SystemClock.ElapsedRealtime() - startTime); } }
public void Finish(Request request) { lock (mCurrentRequests) { mCurrentRequests.Remove(request); } lock (mFinishedListeners) { foreach (IRequestFinishedListener listener in mFinishedListeners) { listener.OnRequestFinished(request); } } if (request.ShouldCache()) { /* * 在该请求完成并缓存后将后面其他重复的 * 请求直接加入到缓存请求队列中 */ lock (mWaitingRequests) { String cacheKey = request.GetCacheKey(); Queue <Request> waitingRequets = null; mWaitingRequests.TryGetValue(cacheKey, out waitingRequets); mWaitingRequests.Remove(cacheKey); if (waitingRequets != null) { if (VolleyLog.DEBUG) { VolleyLog.V("Releasing {0} waiting requests for cacheKey={1}", waitingRequets.Count, cacheKey); } foreach (Request addrequest in waitingRequets) { mCacheQueue.Enqueue(addrequest); } } } } }
public override void Run() { if (DEBUG) { VolleyLog.V("start new dispatcher"); } Process.SetThreadPriority(ThreadPriority.Background); mCache.Initialize(); while (true) { try { Request request = null; if (!mCacheQueue.TryDequeue(out request)) { if (mQuit) { return; } continue; } request.AddMarker("cache-queue-take"); //请求是否已取消 if (request.IsCanceled) { request.Finish("cache-discard-canceled"); continue; } //不存在该缓存 Entry entry = mCache.Get(request.GetCacheKey()); if (entry == null) { request.AddMarker("cache-miss"); mNetworkQueue.Enqueue(request); continue; } //缓存过期 if (entry.IsExpired) { request.AddMarker("cache-hit-expired"); request.CacheEntry = entry; mNetworkQueue.Enqueue(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.CacheEntry = entry; response.Intermediate = true; mDelivery.PostResponse(request, response, () => { mNetworkQueue.Enqueue(request); }); } } catch (Exception) { if (mQuit) { return; } continue; } } }
protected void LogError(String what, String url, long start) { long now = SystemClock.ElapsedRealtime(); VolleyLog.V("HTTP ERROR({0}) {1} ms to fetch {2}", what, (now - start), url); }