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);
                        }
                    }
                }
            }
        }
Esempio n. 4
0
        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);
        }