Volley框架源码

本文主要大概介绍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方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值