Volley框架源码

来源:互联网 发布:淘宝我的空间3d形象 编辑:程序博客网 时间:2024/05/21 09:50

本文主要大概介绍Volley框架源码的骨干东西,内部队列调度,业务流程不详细说。
使用Volley的过程很简单
1、newRequestQueue获取请队列;
2、mQueue.add(stringRequest);将请求加入队列

RequestQueue mQueue = Volley.newRequestQueue(context);StringRequest stringRequest = new StringRequest(StringRequest.Method.GET, url, new Response.Listener<String>() {    @Override    public void onResponse(String response) {        Log.i(TAG, "response:" + response);        iRequest.onResult(response);    }}, new Response.ErrorListener() {    @Override    public void onErrorResponse(VolleyError error) {        Log.e(TAG, "error:" + error);        ExVolleyException exception = new ExVolleyException();        if(error.networkResponse != null){            iRequest.onError(exception.getStatusError(error.networkResponse.statusCode));        }else {            iRequest.onError(exception.getStatusError(500));        }    }}) {    @Override    public Map<String, String> getHeaders() throws AuthFailureError {        return getRequestHeaders(TYPE_HEADER.TYPE_NORMAL);    }    @Override    protected Map<String, String> getParams() throws AuthFailureError {        return super.getParams();    }};mQueue.add(stringRequest);

=======================================================
先从newRequestQueue进入源码分析
一、Volley.class—–>newRequestQueue(Context,HttpStack)

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 {            // 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;}

(1) 主要是根据版本是否大于9(android2.3),初始化HttpStack,主要的区别是:用于网络请求的方式,根据不同的HttpStack初始化,后面用于请求网络的方式不一样,大于9的初始化的HttpStack后面的请求用的HttpUrlConnection而小于9的初始化,后面请求网络用的是httpClient。

(2)初始化BasicNetwork(实现了Network)实际的请求网络的类

(3)初始化一个队列,并将初始化好的缓存和网络请求实例入参
(4)queue.start();

/** * Starts the dispatchers in this queue. */public void start() {    stop();  // Make sure any currently running dispatchers are stopped./** @param cacheQueue Queue of incoming requests for triage* @param networkQueue Queue to post requests that require network to* @param cache Cache interface to use for resolution* @param delivery Delivery interface to use for posting responses*/ // 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();    }}

主要是缓存调度器和网络请求调度器的初始化及start;
两个调度器均继承线程,在RequestQueue构造时,默认缓存调度器线程有4个;
二、mQueue.add(stringRequest); RequestQueue—->add(Request)方法分析

  /**     * Adds a Request to the dispatch queue.     * @param request The request to service     * @return The passed-in request     */    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;        }    }

流程大概就是:
1、 request.setRequestQueue(this);请求帮顶请求队列
2、 mCurrentRequests.add(request);同步加入当前请求队列
3、 request.setSequence(getSequenceNumber());
request.addMarker(“add-to-queue”);
请求加标记
4、判断是否缓存,不缓存就直接放到请求队列: mNetworkQueue.add(request);
5、 判断请求等待队列是否包含当前请求:if(mWaitingRequests.containsKey(cacheKey))及是否有相 同请求正在被处理
如果包含,加入到相同请求的等待队列中,
不包含则创建新的当前请求的空队列,添加当前请求到缓存请求队列中

三、最后
在初始化请求队列的时候重新开启了5个线程,4个缓存调度线程组成的缓存调度器,一个请求调度线程,然后具体的缓存、请求逻辑,请求的实现就交给了调度器,这也是volley框架的核心部分,是很细节的地方,主要关注两类调度器里面run方法。

原创粉丝点击