分析的思路:
1.volley简答访问网络
2.volley完整访问网络流程
3.volley工作的原理
4.volley高效的原因
5.怎样高效的使用volley
6.改造volley
首先,我们不考虑volley,如果是我们自己写一个请求网络的工具;首先会将我们自请求封装一下,然后在扔给线程池请求网络,线程池处理完之后返回结果,我们就处理结果。
其实我看过很多网络请求的框架,几乎都是这样处理的,只不过是中间加了很多优化的方法。volley也是这样处理的。
然后再看一段volley请求网络的简单代码:
RequestQueue mRequestQueue = Volley.newRequestQueue(context);
JsonObjectRequest req = new JsonObjectRequest(URL, null,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
try {
VolleyLog.v("Response:%n %s", response.toString(4));
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
VolleyLog.e("Error: ", error.getMessage());
}
});
mRequestQueue.add(req);
这只是完整的请求过程,但是不是最优的。
首先分析第一句代码:
RequestQueue mRequestQueue = Volley.newRequestQueue(context);
实际上调用的方法是:
public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
//将缓存放在应用的Cache/volley目录下面
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) {
//stack就是请求网络的工具,里面只有一个请求网络的方法
if (Build.VERSION.SDK_INT >= 9) {
stack = new HurlStack();
} else {
// Prior to Gingerbread, HttpUrlConnection was unreliable.
// See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
}
}
Network network = new BasicNetwork(stack);
//创建一个请求管理队列
RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
//启动请求队列,所以获取一个RequestQueue队列之后,不用在start了。直接add请求就行了
queue.start();
return queue;
}
HttpStack、HurlStack、HttpClientStack;BasicNetwork、HttpStack;这两类之间的关系是继承关系;HttpStack的performRequest方法,与Network的performRequest方法之间的关系,实际上就是包裹关系;NetworkResponse就是对HttpResponse的包裹
第二句代码是创建了一个JsonRequest。
第三句代码是将request加入了请求队列中。
上面就是请求网络的一个简单的过程,但是不能用于实战。
下面会阐述理由的
上面mQueue.add(request)这句代码有风险。
在看一下add这个方法,之前先说明下面这4个集合的功能,因为一切操作都是围绕这4个集合来的。
private final Map<String, Queue<Request<?>>> mWaitingRequests =
new HashMap<String, Queue<Request<?>>>();
/**
* The set of all requests currently being processed by this RequestQueue. A Request
* will be in this set if it is waiting in any queue or currently being processed by
* any dispatcher.
*/
private final Set<Request<?>> mCurrentRequests = new HashSet<Request<?>>();
/** The cache triage queue. */
private final PriorityBlockingQueue<Request<?>> mCacheQueue =
new PriorityBlockingQueue<Request<?>>();
/** The queue of requests that are actually going out to the network. */
private final PriorityBlockingQueue<Request<?>> mNetworkQueue =
new PriorityBlockingQueue<Request<?>>();
mNetworkQueue:是用来装真正用来请求网络的request的,mDispatchers就是用来请求网络的线程
mCacheQueue:是装载需要缓存的request的,mCacherDispathers就是负责从缓存中取数据的线程
mWaitingRequests:是装载重复的request
mCurrentRequests:是装载正在被处理的request
下面的add方法是,添加请求的唯一入口;4大集合在里面的功效,上面的表格表示的已经很清楚了。
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;
}
}
上面介绍了简单访问网络的例子;在下一篇博客中会详细介绍volley的使用。