ITKeyword,专注技术干货聚合推荐

注册 | 登录

Part3:Volley传递者原理分析

geekerhw 分享于 2016-07-23

问题产生创建传递者传递的过程一个比较重要的细节问题产生我们先看一下Volley的使用方法://第一步,创建一个RequestQueue队列RequestQueue mQueue = Volley.newRequestQueue(context);

//第二步,创建一个具体类型的对象,这里是StringRequestStringRequest stringRequest = new

StringRequest("http://www.baidu.com",

new Response.Listener<String>() {

@Override

public void onResponse(String response) {

Log.d("TAG", response);

}

}, new Response.ErrorListener() {

@Override

public void onErrorResponse(VolleyError error) {

Log.e("TAG", error.getMessage(), error);

}

}); //第三步,将stringRequest放入queue中queue.add(stringRequest)前面的文章已经分析过了,当我们执行RequestQueue mQueue = Volley.newRequestQueue(context);,它的内部是创建了一个缓存线程和四个网络请求线程,它们会从优先级队列中去取request,如果没有则阻塞,当第三步把相应的请求加入到queue中后,队列中有数据了,线程就会正式执行.那不知道你有没有想过这个问题,请求拿到数据都是在异步线程中的,它到最后是如何跑到onResponse中的(请看上述代码第二步),而且还是这个函数还在主线程中?其实原理非常简单,我们就来稍微分析一下这个类:ExecutorDelivery(网络请求结果传递类,将数据放到主线程中去处理)创建传递者先看一下入口,其实就是第一步时创建,注意Looper.getMainLooper(),它主动绑定了一个主线程中的Looper,这是它能把数据传递到主线程的原因

public RequestQueue(Cache cache, Network network) {

this(cache, network, DEFAULT_NETWORK_THREAD_POOL_SIZE);

}

public RequestQueue(Cache cache, Network network, int threadPoolSize) {

this(cache, network, threadPoolSize,

new ExecutorDelivery(new Handler(Looper.getMainLooper())));

}紧接着看一下ExecutorDelivery的构造函数,看完构造函数后如何构造一个传递这就明白了,现在我们分析一下传递的过程

public ExecutorDelivery(final Handler handler) {

mResponsePoster = new Executor() {

@Override

public void execute(Runnable command) {

// 所有的Runnable通过绑定主线程Looper的Handler对象最终在主线程执行.

handler.post(command);

}

};

}传递的过程传递的入口都是在请求到数据之后,比如CacheDispatcher中得到数据后会调用mDelivery.postResponse(request, response);方法,我们看一下这个方法,毫无疑问,最终执行的是ResponseDeliveryRunnable中的run方法

@Override

public void postResponse(Request<?> request, Response<?> response) {

postResponse(request, response, null);

}

@Override

public void postResponse(Request<?> request, Response<?> response, Runnable runnable) {

request.markDelivered();

mResponsePoster.execute(

new ResponseDeliveryRunnable(request, response, runnable)

);

}我们再看一下ResponseDeliveryRunnable

private class ResponseDeliveryRunnable implements Runnable {

private final Request mRequest;

private final Response mResponse;

private final Runnable mRunnable;

public ResponseDeliveryRunnable(Request request, Response response, Runnable runnable) {

mRequest = request;

mResponse = response;

mRunnable = runnable;

}

@Override

public void run() {

// 如果request被取消,则不回调用户设置的Listener接口

if (mRequest.isCanceled()) {

mRequest.finish("canceled-at-delivery");

return;

}

// 通过response状态标志,来判断是回调用户设置的Listener接口还是ErrorListener接口

if (mResponse.isSuccess()) {

mRequest.deliverResponse(mResponse.result);

} else {

mRequest.deliverError(mResponse.error);

}

if (mResponse.intermediate) {

mRequest.addMarker("intermediate-response");

} else {

// 通知RequestQueue终止该Request请求

mRequest.finish("done");

}

//请注意这句语句,后面会讲

if (mRunnable != null) {

mRunnable.run();

}

}

}先不要管别的逻辑,我们直接跟进mRequest.deliverResponse(mResponse.result);

/** 将解析的String结果传递给用户的回调接口. */

@Override

protected void deliverResponse(String response) {

mListener.onResponse(response);

}在顺便看一下mRequest.deliverError(mResponse.error);

/** 将网络错误传递给回调接口. */

public void deliverError(VolleyError error) {

if (mErrorListener != null) {

mErrorListener.onErrorResponse(error);

}

}把上面两段代码和第二步联系起来看,一切都会真相大白了一个比较重要的细节在ResponseDeliveryRunnable中的run方法里最后一段代码,这里会有人疑惑?为什么又跑到异步线程中去了?

if (mRunnable != null) {

mRunnable.start();

}这个是因为在缓存过期时,会给用户先显示已过期的内容,但是立刻会去网络中请求数据,所以正常的传递逻辑不能少,但必须又包含在异步中请求数据的逻辑,请看入口(在CacheDispatcher中发现缓存失效 后)

mDelivery.postResponse(request, response, new Runnable() {

@Override

public void run() {

try {

mNetworkQueue.put(request);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

});

$(function () {

$('pre.prettyprint code').each(function () {

var lines = $(this).text().split('\n').length;

var $numbering = $('<ul/>').addClass('pre-numbering').hide();

$(this).addClass('has-numbering').parent().append($numbering);

for (i = 1; i <= lines; i++) {

$numbering.append($('<li/>').text(i));

};

$numbering.fadeIn(1700);

});

});

问题产生创建传递者传递的过程一个比较重要的细节问题产生我们先看一下Volley的使用方法://第一步,创建一个RequestQueue队列RequestQueue mQueue = Volley.newRequestQue

相关阅读排行


用户评论

游客

相关内容推荐

最新文章

×

×

请激活账号

为了能正常使用评论、编辑功能及以后陆续为用户提供的其他产品,请激活账号。

您的注册邮箱: 修改

重新发送激活邮件 进入我的邮箱

如果您没有收到激活邮件,请注意检查垃圾箱。