您的位置:首页 > 理论基础 > 计算机网络

谷歌Volley网络框架分析。(一)初始化

2013-11-25 16:19 302 查看
技术水平有限,文章中所描述的错误,请帮助指出。多谢。


Volley提供的功能

简单的讲,提供了如下主要的功能:

1、封装了的异步的RESTful 请求API;

2、一个优雅和稳健的请求队列;

3、一个可扩展的架构,它使开发人员能够实现自定义的请求和响应处理机制;

4、能够使用外部HTTP Client库;

5、缓存策略;

6、自定义的网络图像加载视图(NetworkImageView,ImageLoader等);

7、Volley可以绑定Content的生命周期,例如当Activity销毁时,Volley可以取消响应的网络请求。


StringRequest

这个类可以用来从服务器获取String,如果想自己解析请求响应可以使用这个类,例如返回xml数据。它还可以使用重载的构造函数定制请求。

[java] view
plaincopyprint?

final String URL = "/volley/resource/recent.xml";

StringRequest req = new StringRequest(URL, new Response.Listener<String>() {

@Override

public void onResponse(String response) {

VolleyLog.v("Response:%n %s", response);

}

}, new Response.ErrorListener() {

@Override

public void onErrorResponse(VolleyError error) {

VolleyLog.e("Error: ", error.getMessage());

}

});

// add the request object to the queue to be executed

ApplicationController.getInstance().addToRequestQueue(req);

在添加请求的时候首先创建一个网络请求队列RequestQueue,这应该是核心的请求队列。

Volley只是一个Helper类,帮助创建RequestQueue,

*/
public RequestQueue getRequestQueue() {
// lazy initialize the request queue, the queue instance will be
// created when it is accessed for the first time
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}

return mRequestQueue;
}


newRequestQueue的具体实现代码:

// 在2.3之前的版本,建议使用apache的HttpClient来处理网络请求,在2.3之后的版本建议使用HttpUrlConnection

// 请参考:http://blog.csdn.net/forever_crying/article/details/7021174

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 e) {
}

if (stack == null) {
if (Build.VERSION.SDK_INT >= 9) {
stack = new HurlStack();
} else {
// 在2.3之前的版本,建议使用apache的HttpClient来处理网络请求,在2.3之后的版本建议使用HttpUrlConnection
// 请参考:http://blog.csdn.net/forever_crying/article/details/7021174
// 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);
queue.start();

return queue;
}


Vooley初始化流程:

画了一个初始化的UML图,没学过UML,随便画画,另外求UML的学习书籍,真心不会画啊。。

大概是:Volley.newRequestQueue(),初始化网络请求队列,然后add()消息到RequestQueue,NetworkDispatcher分发消息到NetWork调用HttpStack请求网络,提交本地缓存信息到请求头,NetWork封装HttpStack返回数据,判断是否使用缓存,或者抛出相关的异常。



相关注释:

1、Volley是一个Helper类,主要负责创建出请求队列,并且启动队列消息的循环。

2、HttpStack负责解析网络请求,performRequest返回一个Apache的HttpResponse,确保返回的Response有StatusLine

注:在2.3之前的版本,建议使用apache的HttpClient来处理网络请求,在2.3之后的版本建议使用HttpUrlConnection
http://blog.csdn.net/forever_crying/article/details/7021174
HurlStack,使用HttpUrlConnection,解析网络请求;HttpClientStack使用HttpClient解析网络请求

3、Network封装了HttpStack的网络请求,performRequest方法直接返回一个NetworkResponse,处理了请求异常抛出VolleyError。

4、NetworkDispatcher网络调度(线程池),分发网络请求到NetWork。

/**
* RequestQueue.start() 启动缓存调度和网络调度
*/
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();

// Create network dispatchers (and corresponding threads) up to the pool size.
for (int i = 0; i < mDispatchers.length; i++) {
NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,
mCache, mDelivery);
mDispatchers[i] = networkDispatcher;
networkDispatcher.start();
}
}


//BaseNetWork的主要代码 添加了一些注释
@Override
public NetworkResponse performRequest(Request<?> request) throws VolleyError {
long requestStart = SystemClock.elapsedRealtime();
while (true) {
HttpResponse httpResponse = null;
byte[] responseContents = null;
Map<String, String> responseHeaders = new HashMap<String, String>();
try {
// Gather headers.
Map<String, String> headers = new HashMap<String, String>();//请求头信息。
addCacheHeaders(headers, request.getCacheEntry());//添加本地缓存头信息
httpResponse = mHttpStack.performRequest(request, headers);//发出网络请求
StatusLine statusLine = httpResponse.getStatusLine();
int statusCode = statusLine.getStatusCode();//HTTP状态码

responseHeaders = convertHeaders(httpResponse.getAllHeaders());//解析头信息
// Handle cache validation.
if (statusCode == HttpStatus.SC_NOT_MODIFIED) {//可以使用缓存数据
return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED,
request.getCacheEntry().data, responseHeaders, true);
}

// Some responses such as 204s do not have content.  We must check.
if (httpResponse.getEntity() != null) {//将返回数据 转化为byte数据
responseContents = entityToBytes(httpResponse.getEntity());
} else {//如果没有返回内容。
// Add 0 byte response as a way of honestly representing a
// no-content request.
responseContents = new byte[0];
}

// if the request is slow, log it.
long requestLifetime = SystemClock.elapsedRealtime() - requestStart;
//如果请求时间过长 则打印Log
logSlowRequests(requestLifetime, request, responseContents, statusLine);

if (statusCode < 200 || statusCode > 299) {//服务器返回异常 则抛出IOException
throw new IOException();
}
return new NetworkResponse(statusCode, responseContents, responseHeaders, false);
} catch (SocketTimeoutException e) {//链接超时 尝试重新链接 如果达到尝试次数 则会抛出VolleyError异常,此次请求则结束。
attemptRetryOnException("socket", request, new TimeoutError());
} catch (ConnectTimeoutException e) {//链接超时 尝试重新链接 如果达到尝试次数 则会抛出VolleyError异常,此次请求则结束。
attemptRetryOnException("connection", request, new TimeoutError());
} catch (MalformedURLException e) {//Bad URL
throw new RuntimeException("Bad URL " + request.getUrl(), e);
} catch (IOException e) {
int statusCode = 0;
NetworkResponse networkResponse = null;
if (httpResponse != null) {
statusCode = httpResponse.getStatusLine().getStatusCode();
} else {//{//如果没有返回httpResponse,就说明没连接
throw new NoConnectionError(e);
}
VolleyLog.e("Unexpected response code %d for %s", statusCode, request.getUrl());
if (responseContents != null) {
networkResponse = new NetworkResponse(statusCode, responseContents,
responseHeaders, false);
if (statusCode == HttpStatus.SC_UNAUTHORIZED ||
statusCode == HttpStatus.SC_FORBIDDEN) {//认证失败异常,重试
attemptRetryOnException("auth",
request, new AuthFailureError(networkResponse));
} else {//服务器异常
// TODO: Only throw ServerError for 5xx status codes.
throw new ServerError(networkResponse);
}
} else {//网络异常
throw new NetworkError(networkResponse);
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: