Volley分析(1)

接下来我会写一个分析volley源码的系列。

分析的思路:

1.volley简答访问网络

2.volley完整访问网络流程

3.volley工作的原理

4.volley高效的原因

5.怎样高效的使用volley

6.改造volley


首先,我们不考虑volley,如果是我们自己写一个请求网络的工具;首先会将我们自请求封装一下,然后在扔给线程池请求网络,线程池处理完之后返回结果,我们就处理结果。

其实我看过很多网络请求的框架,几乎都是这样处理的,只不过是中间加了很多优化的方法。volley也是这样处理的。

然后再看一段volley请求网络的简单代码:

RequestQueue mRequestQueue = Volley.newRequestQueue(context);
JsonObjectRequest req = new JsonObjectRequest(URL, null,
       new Response.Listener<JSONObject>() {
           @Override
           public void onResponse(JSONObject response) {
               try {
                   VolleyLog.v("Response:%n %s", response.toString(4));
               } catch (JSONException e) {
                   e.printStackTrace();
               }
           }
       }, new Response.ErrorListener() {
           @Override
           public void onErrorResponse(VolleyError error) {
               VolleyLog.e("Error: ", error.getMessage());
           }
       });
mRequestQueue.add(req);

这只是完整的请求过程,但是不是最优的。

首先分析第一句代码:

RequestQueue mRequestQueue = Volley.newRequestQueue(context);

实际上调用的方法是:

    public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
        //将缓存放在应用的Cache/volley目录下面
        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) {
            //stack就是请求网络的工具,里面只有一个请求网络的方法
            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);
        //启动请求队列,所以获取一个RequestQueue队列之后,不用在start了。直接add请求就行了
        queue.start();

        return queue;
    }

HttpStack、HurlStack、HttpClientStack;BasicNetwork、HttpStack;这两类之间的关系是继承关系;HttpStack的performRequest方法,与Network的performRequest方法之间的关系,实际上就是包裹关系;NetworkResponse就是对HttpResponse的包裹


第二句代码是创建了一个JsonRequest。

第三句代码是将request加入了请求队列中。

上面就是请求网络的一个简单的过程,但是不能用于实战。

下面会阐述理由的

上面mQueue.add(request)这句代码有风险。

在看一下add这个方法,之前先说明下面这4个集合的功能,因为一切操作都是围绕这4个集合来的。

private final Map<String, Queue<Request<?>>> mWaitingRequests =
            new HashMap<String, Queue<Request<?>>>();

    /**
     * The set of all requests currently being processed by this RequestQueue. A Request
     * will be in this set if it is waiting in any queue or currently being processed by
     * any dispatcher.
     */
    private final Set<Request<?>> mCurrentRequests = new HashSet<Request<?>>();

    /** The cache triage queue. */
    private final PriorityBlockingQueue<Request<?>> mCacheQueue =
        new PriorityBlockingQueue<Request<?>>();

    /** The queue of requests that are actually going out to the network. */
    private final PriorityBlockingQueue<Request<?>> mNetworkQueue =
        new PriorityBlockingQueue<Request<?>>();

mNetworkQueue:是用来装真正用来请求网络的request的,mDispatchers就是用来请求网络的线程

mCacheQueue:是装载需要缓存的request的,mCacherDispathers就是负责从缓存中取数据的线程

mWaitingRequests:是装载重复的request

mCurrentRequests:是装载正在被处理的request


下面的add方法是,添加请求的唯一入口;4大集合在里面的功效,上面的表格表示的已经很清楚了。

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

上面介绍了简单访问网络的例子;在下一篇博客中会详细介绍volley的使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值