本文大篇幅参考此篇文章,大家可以结合两篇文章看一下
文章目录
1. Volley简介
在很早以前,如果Android开发者想使用网络请求的话,必须自己通过HttpClient
或者HttpURLConnection
编写代码来访问。但是他两的用法还是很复杂的,如果不适当的封装的话,就会有很多多余代码甚至效率降低。所以当时出现了很多第三方网络通信框架,但是都是第三方的,而谷歌官方一直没有作为。
最终在2013年,谷歌终于意识到了问题,于是他们推出了一个官方的全新的网络框架——Volley。Volley它又能非常简单的进行HTTP通信,又能轻松加载网络上的图片。他的设计目的就是应对数据量不大但是频发的网络操作,但是对于下载等需要大数据量的网络操作,他就不太适合。
2. 源码解析
2.1 从RequestQueue入手
如果你使用Volley的话,就会发现Volley不管进行什么操作,首先第一步就是先创建RequestQueue对象。
所以我们就可以认定他为Volley的入口。
创建RequestQueue的方法是RequestQueue mQueue = Volley.newRequestQueue(getApplicationContext());
,我们就看看newRequestQueue
干了什么:
public static RequestQueue newRequestQueue(Context context, BaseHttpStack stack) {
BasicNetwork network;
if (stack == null) {
if (Build.VERSION.SDK_INT >= 9) {
network = new BasicNetwork(new HurlStack());
} else {
// 在Android 2.3之前,HttpURLConnection是不可靠的。
// 请参阅:http://android-developers.blogspot.com/2011/09/androids-http-clients.html
// 在将来的某个时候,我们将把minsdkversion移到Android 2.2之上,
// 并可以删除这个回退(连同所有ApacheHTTP代码)。
String userAgent = "volley/0";
try {
String packageName = context.getPackageName();
PackageInfo info =
context.getPackageManager().getPackageInfo(packageName, /* flags= */ 0);
userAgent = packageName + "/" + info.versionCode;
} catch (NameNotFoundException e) {
}
network =
new BasicNetwork(
new HttpClientStack(AndroidHttpClient.newInstance(userAgent)));
}
} else {
network = new BasicNetwork(stack);
}
return newRequestQueue(context, network);
}
调用方法后,先查看Android版本是否大于等于2.3,如果大于则调用基于HttpURLConnection
的HurlStack
,否则调用基于HttpClient
的HttpClientStack
。接下来创建BasicNetwork
并调用newRequestQueue(context, network)
方,我们再来看看这个newRequestQueue()
方法:
private static RequestQueue newRequestQueue(Context context, Network network) {
final Context appContext = context.getApplicationContext();
// 对缓存目录使用惰性供应商,以便可以在主线程上调用newRequestQueue(),
// 而不会导致严格的模式冲突。
DiskBasedCache.FileSupplier cacheSupplier =
new DiskBasedCache.FileSupplier() {
private File cacheDir = null;
@Override
public File get() {
if (cacheDir == null) {
cacheDir = new File(appContext.getCacheDir(), DEFAULT_CACHE_DIR);
}
return cacheDir;
}
};
RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheSupplier), network);
queue.start();
return queue;
}
可以看到,这个方法主要为Volley创建了一个硬盘缓存DiskBasedCache
,然后通过这个磁盘缓存和Network
创建了一个RequestQueue
对象,并调用了start()
方法,接下来我们看下start()
方法:
public void start() {
stop();
// 确保当前运行的所有调度程序都已停止。
// 创建缓存调度器并开始它。
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();
}
}
CacheDispatcher
是一个缓存调度线程,并调用了start()
方法。在循环中调用NetworkDispatcher
的start()
方法。NetworkDispatcher
是网络调度线程,默认情况下mDispatchers.length
为4,默认开启了4个调度线程,外加1个缓存调度线程,总共5个线程。
接下来Volley会创建各种Request
,并调用RequestQueue
的add()
方法:
public <T> Request<T> add(Request<T> request) {
// 将请求标记为属于此队列,并将其添加到当前请求集。
request.setRequestQueue(this);
synchronized (mCurrentRequests) {
//mCurrentRequests是一个HashSet
mCurrentRequests.add(request);
}
// 按添加的顺序处理请求。
request.setSequence(getSequenceNumber());
request.addMarker("add-to-queue");
sendRequestEvent(request, RequestEvent.REQUEST_QUEUED);
// 如果请求是不可执行的,跳过缓存队列,然后直接进入网络。
if (!request.shouldCache()