Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android Volley分析(一)

Android Volley分析(一)

編輯:關於Android編程

Volley是Android系統下的一個網絡通信庫,為Android提供簡單快速的網絡操作(Volley:Esay, Fast Networking for Android),下面是它的結構:

vc34wue1xLv5tKGy2df3o7rH68fzus3P7NOmo6zSssrH1+67+bG+tcS4xcTuoaO/zbuntsu3orP2x+vH86Ost/7O8bbLt7W72M/s06a1xNfWvdrK/b7do6y/zbuntsu94s72tcO1vc/r0qq1xL3hufuho1ZvbGxledT1w7TJ6LzG1eLQqbv5sb61xLjFxO6jvzwvcD4KPHA+0ruhotfpvP48L3A+CjxwPjGhok5ldHdvcms8L3A+CjxwPs34wuey2df3tcS2qNLlo6y0q8jrx+vH81JlcXVlc3SjrLXDtb3P7NOmTmV0d29ya1Jlc3BvbnNlPC9wPgo8cD48L3A+CjxwcmUgY2xhc3M9"brush:java;">public interface Network { /** * Performs the specified request. * @param request Request to process * @return A {@link NetworkResponse} with data and caching metadata; will never be null * @throws VolleyError on errors */ public NetworkResponse performRequest(Request request) throws VolleyError; }
2、Request

請求的定義,網絡請求的參數、地址等信息

public Request(int method, String url, Response.ErrorListener listener) {
        mMethod = method;
        mUrl = url;
        mErrorListener = listener;
        setRetryPolicy(new DefaultRetryPolicy());

        mDefaultTrafficStatsTag = findDefaultTrafficStatsTag(url);
    }

在Request中有兩個抽象方法需要子類去實現,

一個是 parseNetworkResponse,就是說對於返回的數據,需要怎麼去解析,解析成什麼類型的數據。一個具體的請求,應該知道自己想要什麼結果,比如StringRequest就是將結果解析成String,而ImageRequest則是將結果解析成Bitmap;

另一個是 deliverResponse,用於解析完成後將結果傳遞出去。這裡傳入的是已經解析的結果,子類負責處理返回的解析結果,一般會在裡面通過listener返回到應用的場景下。

/**
     * Subclasses must implement this to parse the raw network response
     * and return an appropriate response type. This method will be
     * called from a worker thread.  The response will not be delivered
     * if you return null.
     * @param response Response from the network
     * @return The parsed response, or null in the case of an error
     */
    abstract protected Response parseNetworkResponse(NetworkResponse response);

    

    /**
     * Subclasses must implement this to perform delivery of the parsed
     * response to their listeners.  The given response is guaranteed to
     * be non-null; responses that fail to parse are not delivered.
     * @param response The parsed response returned by
     * {@link #parseNetworkResponse(NetworkResponse)}
     */
    abstract protected void deliverResponse(T response);

3、NetworkResponse

網絡請求通用返回結果,存儲在data中

    public NetworkResponse(int statusCode, byte[] data, Map headers,
            boolean notModified) {
        this.statusCode = statusCode;
        this.data = data;
        this.headers = headers;
        this.notModified = notModified;
    }


4、Response

響應結果的封裝,最終結果result,緩存結構cacheEntry,出錯信息error

private Response(T result, Cache.Entry cacheEntry) {
        this.result = result;
        this.cacheEntry = cacheEntry;
        this.error = null;
    }

二、執行過程

有了上面的基本數據結構,之後就是考慮怎麼去操作這些結構,完成從請求到響應的整個過程。這裡是整個Volley最核心的部分,也是體現作者設計思想的部分,涉及到任務調度、異步處理等。

1、RequestQueue

請求隊列,所有請求都會通過RequestQueue的add方法加入到內部的隊列裡來等待處理,當請求結束得到響應結果後會調用finish方法將請求移出請求隊列。

RequestQueue中包含以下成員:

Cache 緩存結構,用於緩存響應結果;Network 網絡操作的實現NetworkDispatcher 網絡任務調度器CacheDispatcher 緩存任務調度器ResponseDelivery 響應投遞,用於將結果從工作線程轉移到UI線程 cacheQueue 緩存任務隊列networkQueue 網絡任務隊列

RequestQueue完成兩項工作:

啟動、停止調度器:

/**
     * Starts the dispatchers in this queue.
     */
    public void start() {
        stop();  // Make sure any currently running dispatchers are stopped.
        // 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();
        }
    }

    /**
     * Stops the cache and network dispatchers.
     */
    public void stop() {
        if (mCacheDispatcher != null) {
            mCacheDispatcher.quit();
        }
        for (int i = 0; i < mDispatchers.length; i++) {
            if (mDispatchers[i] != null) {
                mDispatchers[i].quit();
            }
        }
    }

將請求添加到相應的隊列中,之後各個調度器會自行取出處理

    public  Request add(Request 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> stagedRequests = mWaitingRequests.get(cacheKey);
                if (stagedRequests == null) {
                    stagedRequests = new LinkedList>();
                }
                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;
        }
    }

從上面可以看出,一個請求不要求緩存的話會被直接加到networkQueue中,否則會加到cacheQueue中。那調度器是怎麼自行取出來並進行處理呢?

2、CacheDispatcher,NetworkDispatcher

調度器是線程,隊列阻塞,有請求就執行,沒有就等待。對緩存調度器CacheDispatcher,如果在緩存中沒有找到響應結果,就會將請求添加到網絡調度器NetworkDispatcher中

while (true) {
            try {
                // Get a request from the cache triage queue, blocking until
                // at least one is available.
                final Request request = mCacheQueue.take();
                request.addMarker("cache-queue-take");

                // If the request has been canceled, don't bother dispatching it.
                if (request.isCanceled()) {
                    request.finish("cache-discard-canceled");
                    continue;
                }

                // Attempt to retrieve this item from cache.
                Cache.Entry entry = mCache.get(request.getCacheKey());
                if (entry == null) {
                    request.addMarker("cache-miss");
                    // Cache miss; send off to the network dispatcher.
                    mNetworkQueue.put(request);
                    continue;
                }

                // If it is completely expired, just send it to the network.
                if (entry.isExpired()) {
                    request.addMarker("cache-hit-expired");
                    request.setCacheEntry(entry);
                    mNetworkQueue.put(request);
                    continue;
                }

                // We have a cache hit; parse its data for delivery back to the request.
                request.addMarker("cache-hit");
                Response response = request.parseNetworkResponse(
                        new NetworkResponse(entry.data, entry.responseHeaders));
                request.addMarker("cache-hit-parsed");

                if (!entry.refreshNeeded()) {
                    // Completely unexpired cache hit. Just deliver the response.
                    mDelivery.postResponse(request, response);
                } else {
                    // Soft-expired cache hit. We can deliver the cached response,
                    // but we need to also send the request to the network for
                    // refreshing.
                    request.addMarker("cache-hit-refresh-needed");
                    request.setCacheEntry(entry);

                    // Mark the response as intermediate.
                    response.intermediate = true;

                    // Post the intermediate response back to the user and have
                    // the delivery then forward the request along to the network.
                    mDelivery.postResponse(request, response, new Runnable() {
                        @Override
                        public void run() {
                            try {
                                mNetworkQueue.put(request);
                            } catch (InterruptedException e) {
                                // Not much we can do about this.
                            }
                        }
                    });
                }

NetworkDispatcher則是負責執行網絡操作獲取響應,調用Request解析響應從而得到指定的返回數據類型,將結果加入緩存,使用delivery將結果返回到UI線程。


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved