Volley库源码分析(下)

/*** @title performRequest执行各种Request请求并以NetworkResponse的形式返回结果* @param Request* @return NetworkResponse* @throws VolleyError* 定义:{@link Network#performRequest(Request)}* 被调:{@link NetworkDispatcher#run()}**/@Override//NetworkDispatcher的run()方法中调用public NetworkResponse performRequest(Request<?> request) throws VolleyError {long requestStart = SystemClock.elapsedRealtime();//开始请求时间while (true) {HttpResponse httpResponse = null;//apache的请求结果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);//去调用mHttpStack的实现方法执行请求StatusLine statusLine = httpResponse.getStatusLine();//获取http状态线int statusCode = statusLine.getStatusCode();//获取状态码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);}//把HttpEntity转化为byte[]数据responseContents = entityToBytes(httpResponse.getEntity());// if the request is slow, log it.//如果请求很慢,就打印出来看一下long requestLifetime = SystemClock.elapsedRealtime() – requestStart;logSlowRequests(requestLifetime, request, responseContents, statusLine);//打印//连接正常但是返回无内容,抛出IO异常if (statusCode != HttpStatus.SC_OK && statusCode != HttpStatus.SC_NO_CONTENT) {throw new IOException();}return new NetworkResponse(statusCode, responseContents, responseHeaders, false);} catch (SocketTimeoutException e) {//读取超时,重试attemptRetryOnException("socket", request, new TimeoutError());} catch (ConnectTimeoutException e) {//连接超时,重试attemptRetryOnException("connection", request, new TimeoutError());} catch (MalformedURLException e) {//Bad URLthrow new RuntimeException("Bad URL " + request.getUrl(), e);} catch (IOException e) {//IO异常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);//只有状态码为5XX才抛出服务器异常}} else {//网络异常throw new NetworkError(networkResponse);}}}}

A:先是通过mHttpStack把请求执行并且获取它的响应结果,根据HttpStatus做出各种判断。

B:然后再把httpResponse的Entity转化为ByteArray,并处理各种发生的异常。

C:最后的过程是这样的:通过Volley创建一个RequestQueue请求队列,当这个队列开始运作的时候会启动NetworkDispatcher这个工作线程,而BasicNetwork的performRequest()的方法就在NetworkDispatcher线程run()方法中调用,然后通过mHttpStack的performRequest()方法获取一个networkResponse,,在NetworkDispatcher线程把这个networkResponse转化为期望的数据类型,比如Response<String>,Response<Json>,Response<Bitmap>。

图片下载部分分析

这部分主要集中在将网络请求转化为图片,以及在未有本地图片时显示空图等。

开发者主要和NetworkImageView打交道,NetworkImageView继承ImageView,可以直接在xml布局中使用NetworkImageView,但是该类具有自动下载图片、缓存图片和在无本地图片时显示空图的功能。

public class NetworkImageView extends ImageView {/** The URL of the network image to load */private String mUrl;/*** Resource ID of the image to be used as a placeholder until the network image is loaded.*/private int mDefaultImageId;//无本地图片时显示的空图/*** Resource ID of the image to be used if the network response fails.*/private int mErrorImageId;/** Local copy of the ImageLoader. */private ImageLoader mImageLoader;/** Current ImageContainer. (either in-flight or finished) */private ImageContainer mImageContainer;……/*** Loads the image for the view if it isn't already loaded.* @param isInLayoutPass True if this was invoked from a layout pass, false otherwise.*/private void loadImageIfNecessary(final boolean isInLayoutPass) {int width = getWidth();int height = getHeight();……// The pre-existing content of this view didn't match the current URL. Load the new image// from the network.ImageContainer newContainer = mImageLoader.get(mUrl,new ImageListener() {@Overridepublic void onErrorResponse(VolleyError error) {if (mErrorImageId != 0) {setImageResource(mErrorImageId);}}@Overridepublic void onResponse(final ImageContainer response, boolean isImmediate) {// If this was an immediate response that was delivered inside of a layout// pass do not set the image immediately as it will trigger a requestLayout// inside of a layout. Instead, defer setting the image by posting back to// the main thread.if (isImmediate && isInLayoutPass) {post(new Runnable() {@Overridepublic void run() {onResponse(response, false);}});return;}if (response.getBitmap() != null) {setImageBitmap(response.getBitmap());} else if (mDefaultImageId != 0) {setImageResource(mDefaultImageId);}}});// update the ImageContainer to be the new bitmap container.mImageContainer = newContainer;}……}

所以关键在于mImageLoader.get()方法。图片下载中最关键的类是ImageLoader,负责帮助从远端URL下载图片和缓存图片。注意,这个类的实例必须从主线程创建,所有的responses也必须分发到主线程。

其实每一朵花,都有它自己的生命,

Volley库源码分析(下)

相关文章:

你感兴趣的文章:

标签云: