[Android] Volley源碼分析(一)體繫結構,androidvolley源碼

來源:互聯網
上載者:User

[Android] Volley源碼分析(一)體繫結構,androidvolley源碼

       Volley:google出的一個用於非同步處理的架構。由於本身的易用性和良好的api,使得它能得以廣泛的應用。我還是一如既往從源碼的方向上來把控它。我們先通過一段簡單的代碼來瞭解Volley

RequestQueue queue = Volley.newRequestQueue(this);ImageRequest imagerequest = new ImageRequest(url, new Response.Listener<Bitmap>(){            @Override            public void onResponse(Bitmap response) {                // TODO Auto-generated method stub                System.out.println(">>>bitmap = "+response);            }}, 300,                200,                Config.ARGB_8888,                new ErrorListener() {                    @Override                    public void onErrorResponse(VolleyError error) {                        // TODO Auto-generated method stub                        System.out.println("error "+error);                    }                });        queue.add(imagerequest);

     俗話說,“對比方顯美”,代碼架構也如此。我們先回想一下我們過去建立bitmapcache的慘痛經曆吧。首先我們使用的cache功能比較單一,往往只是支援記憶體cache,淘汰策略一般是通過數量或者容量限制。每寫一個app都自成一套。此外,一旦我們脫離了程式,我們將不再獲得我們Bitmap的中繼資料,比如請求網路連結,資源描述符等等,而且對於同一個網路請求我們要用單獨的裝飾器來攔截。

      當然,我之所以列舉這些出來,是因為在Volley裡面已經很好的解決了這些問題,當你下載了Volley的源碼編譯以後,你會發現,Volley所涵蓋的功能遠比你考慮的要多。而且這些東西,已經被很好的封裝起來。而且Volley的代碼讀起來也非常的順口,並不像Android原生的一些代碼一樣又臭又長。如果說Volley是一種好的開源架構,不如說Volley是一套現在看起來還不錯的設計模式。而且從Volley所提供的有些介面來說,Volley已經將很大部分封裝在架構內部,對於api調用者來說,無疑是個福音。

      Volley裡面普遍採用了生產消費者模式,當然你說它是觀察者其實也無可厚非。生產者通過生產產品來通知消費者消費,這種簡單的模型在多種架構中使用到。這裡的消費者是叫Request的類。這個類將分發給CacheDispatcher和NetworkDispatcher來進行消費。從我們寫Cache的經驗來說我們對Cache的處理模式普遍一致,大都是看Cache中是否存在,如果存在,則load from disk.否則請求網路。其實Volley的處理大同小異。對於允許Cache的請求。Request將被RequestQueue分發到CacheDispatcher消費。如果CacheDispatcher消費不了,那麼就將分發給NetworkDispatcher。這種模式非常像職責鏈。其實在這種分發下,存在一個Volley的亮點之一,就是url攔截。RequestQueue本身維護一個暫存列表,而這種暫存列表能很好的攔截重複的URL請求。由CacheDispatcher處理的請求,如果在disk cache中存在,那麼將通過Request的parseNetworkResponse 介面進行解析,我們看一下對於一個圖片請求他的parse流程:

private Response<Bitmap> doParse(NetworkResponse response) {        byte[] data = response.data;        BitmapFactory.Options decodeOptions = new BitmapFactory.Options();        Bitmap bitmap = null;        if (mMaxWidth == 0 && mMaxHeight == 0) {            decodeOptions.inPreferredConfig = mDecodeConfig;            bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, decodeOptions);        } else {            // If we have to resize this image, first get the natural bounds.            decodeOptions.inJustDecodeBounds = true;            BitmapFactory.decodeByteArray(data, 0, data.length, decodeOptions);            int actualWidth = decodeOptions.outWidth;            int actualHeight = decodeOptions.outHeight;            // Then compute the dimensions we would ideally like to decode to.            int desiredWidth = getResizedDimension(mMaxWidth, mMaxHeight,                    actualWidth, actualHeight);            int desiredHeight = getResizedDimension(mMaxHeight, mMaxWidth,                    actualHeight, actualWidth);            // Decode to the nearest power of two scaling factor.            decodeOptions.inJustDecodeBounds = false;            // TODO(ficus): Do we need this or is it okay since API 8 doesn't support it?            // decodeOptions.inPreferQualityOverSpeed = PREFER_QUALITY_OVER_SPEED;            decodeOptions.inSampleSize =                findBestSampleSize(actualWidth, actualHeight, desiredWidth, desiredHeight);            Bitmap tempBitmap =                BitmapFactory.decodeByteArray(data, 0, data.length, decodeOptions);            // If necessary, scale down to the maximal acceptable size.            if (tempBitmap != null && (tempBitmap.getWidth() > desiredWidth ||                    tempBitmap.getHeight() > desiredHeight)) {                bitmap = Bitmap.createScaledBitmap(tempBitmap,                        desiredWidth, desiredHeight, true);                tempBitmap.recycle();            } else {                bitmap = tempBitmap;            }        }        if (bitmap == null) {            return Response.error(new ParseError(response));        } else {            return Response.success(bitmap, HttpHeaderParser.parseCacheHeaders(response));        }    }
    我們看到,它產生了一個response對象返回給了上層,最後再由Delivery來分發Reponse.其實我們可以看出,整個Volley的Cache設計相對簡單,而且還有很大的改造空間。比如,對於Delivery的分發機制,完全可以用EventBus這類的事件驅動的架構來完成。還有Bitmap的產生,可以採用記憶體對應檔的方式來減少記憶體開銷。當然,這些小甜點並不影響Volley做為一個非常優秀的代碼而存在。在Volley裡面Delivery的本質是一個線程池,採用線程池post的方式可以有效避免Volley的CacheDispatcher和NetWorkDispatcher因為處理reponse而造成的線程阻塞。

    我們再回頭看看如果我們在Cache中不存在,我們請求網路的情況。Volley對平台的請求介面進行了封裝,你可能採用的是HttpClient,當然也有可能是直接使用HttpUrlConnection。對於上層來說,為了屏蔽掉這種平台的差異性,抽象出一個叫做Network的網路介面,這是一種橋接的模式。而當你使用某種方式網路獲得資料以後,NetworkDispatcher將資料put到Cache中.通過Delivery分發Request回調以後,調用Request的finish方法將自己從RequestQueue的暫存表中刪除。

    好的,是不是覺得Volley代碼設計的是如此的思路清晰,本章我們先介紹Volley的主體結構,下面會通過兩章節來描述Volley的兩大模組:Cache和Network設計。







android 源碼 源碼分析 android源碼分析 ,如何跟蹤android源碼,請以settings為例,初學不太會,請指點settings代碼載入eclipse工程加入相關jar包慢慢從入口開始研究唄
如何進行android源碼分析要想看其結構需要看google提供張架構圖對著慢慢看分析分析吧源碼裡工程單獨作Android工程匯入Eclipse裡需要匯入所有Android源碼才關於使用git下載源碼方法網上搜大把還自己去try吧問出來只有自己動手

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.