Volley学习笔记
来源:互联网 发布:rsync windows 编辑:程序博客网 时间:2024/06/05 08:06
原文地址https://github.com/XanthusL/blog-gen
虽然更倾向于retrofit + okhttp,但目前的项目中还在用Volley,从学习的角度扒一扒Volley的源码吧
主要是分析Volley的部分实现,不再涉及具体使用和二次封装
Volley.java
Volley.java
用来创建 RequestQueue
,有两个用来重载静态方法和一个常量(默认的磁盘缓存目录),核心代码如下:
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 ignored) { } 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;}
- 1.创建缓存目录
- 2.生成内容为
包名/版本号
的UA,默认为”volley/0” - 3.如果未指定stack,在api9以上的设备上使用基于HttpURLConnection的stack,更旧是设备上则是用HttpClient实现的stack。传入的HttpStack为
接口类型
,因此可以使用自己的HttpStack实现(如okhttp)。 - 4.创建BasicNetwork对象和DiskBasedCache对象
- 5.通过4中的对象构造一个RequestQueue,并调用start()方法后将其返回
RequestQueue.java
RequestQueue有一个缓存dispatcher和一组网络dispatcher,其数量(线程池大小)可指定,默认为4.
stop()方法将所有dispatcher停止
public void stop() { if (mCacheDispatcher != null) { mCacheDispatcher.quit(); } for (int i = 0; i < mDispatchers.length; i++) { if (mDispatchers[i] != null) { mDispatchers[i].quit(); } }}
start()方法则是先调用stop方法,再创建每一个dispatcher并调用其start方法(dispatcher继承Thread)
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(); for (int i = 0; i < mDispatchers.length; i++) { NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork, mCache, mDelivery); mDispatchers[i] = networkDispatcher; networkDispatcher.start(); }}
add()方法将请求添加至队列。
如果不使用缓存,则直接添加至网络队列并返回,不再使用缓存队列;
使用缓存时,则先根据cacheKey判断是否有正在等待的相同请求,如果有就加入该key对应的Queue排队,没有则添加到缓存队列并将key对应的Queue置空
public <T> Request<T> add(Request<T> request) { // 将该请求标记为属于当前队列,并加入mCurrentRequests 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; }}
Dispatcher
请求添加到队列后,由Dispatcher处理。NetworkDispatcher和CacheDispatcher都是Thread的子类,主要逻辑在run()方法
- NetworkDispatcher.java核心代码如下
// ... // ... // Take a request from the queue. // 此处mQueue的类型为BlockingQueue<Request<?>>, // take()方法有可能阻塞,类似与Linux下的pipe, // Looper.loop()方法中也有同样的用法(生产者消费者模型) request = mQueue.take(); // ... // ... // Perform the network request. NetworkResponse networkResponse = mNetwork.performRequest(request); // ... // ... // 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通过executor和handler将结果发出,由Looper线程处理,通常是主线程 mDelivery.postResponse(request, response);
- CacheDispatcher.java核心代码如下
与NetworkDispatcher的实现类似,但CacheDispatcher需要对缓存数据进行判断,是否存在、是否过期、是否需要刷新等。根据判断结果决定是否需要将请求加入网络队列交给NetworkDispatcher处理
// Get a request from the cache triage queue, blocking until // at least one is available. final Request<?> request = mCacheQueue.take(); // ... // ... // 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. // ... // ... mDelivery.postResponse(request, response, new Runnable() { @Override public void run() { try { mNetworkQueue.put(request); } catch (InterruptedException e) { // Not much we can do about this. } } }); }
嗯,还没写完
阅读全文
0 0
- Volley学习笔记
- volley学习笔记
- volley学习笔记
- Volley学习笔记
- volley框架学习笔记
- Volley的学习笔记
- volley学习笔记
- Volley学习笔记
- Volley学习笔记
- Volley学习笔记二
- volley学习笔记三
- volley学习笔记四
- Volley学习笔记
- Android Volley 学习笔记 1
- Volley源码学习笔记1
- Android Volley框架学习笔记
- Android-volley框架学习笔记
- 【Android开发】Volley学习笔记
- 9.27 [NOIP模拟]数据结构 不正常团伙 莫队/主席树
- 如何输出一个菱形
- 上传图片
- ajax实现异步请求的json方式;
- 菱形
- Volley学习笔记
- elastic search 基本概念
- Java之——Web项目中DLL文件动态加载方法
- hdu 4027 Can you answer these queries?
- eclipse使用插件远程调试Hadoop
- 使用Socket进行远程调用
- 实验一Linux操作系统的安装
- Postgresql相关问题
- 【Linux】命令整理(一)