Volley分析(1)

来源:互联网 发布:淘宝急需开通直播 编辑:程序博客网 时间:2024/06/08 18:41
接下来我会写一个分析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的使用。

0 0
原创粉丝点击