Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android資訊 >> Android ImageLoader框架之基本架構

Android ImageLoader框架之基本架構

編輯:Android資訊

前言

在Android開發中,ImageLoader應該算得上是最重要的開源庫之一,由於項目原因(不能使用開源庫),前段時間自己也是需要實現一個簡單的ImageLoader,因此誕生了這個庫,我們暫且叫它為SimpleImageLoader。就目前而言,你上網查ImageLoader資料的時候,基本上能夠找到很簡單的實現,基本上一個類就把所有的工作給做了,這就顯得很不專業了嘛,很多時候我們不只是需要實現功能,而是希望能夠在實現功能的同時在設計層面有所提升。

SimpleImageLoader分享出來的主要目的並不是說替代那些著名開源庫,而是提供一個簡單的、又有一定參考價值的ImageLoader實現讓一些需要幫助的人學習,在深入了解實現的同時學到知識,也能夠體會到在設計一個開源庫時應該要做哪些考慮、做哪些取捨、有什麼模式,當然在了解了ImageLoader的實現之後再去使用專業的開源庫也會更加的得心應手,出現問題的時候自己也能夠不太費力地去究其原因。在提升自己的同時也能夠了解一些開源庫的設計基本原則,這也是我的博客中一直主張的觀點。

當然限於本人水平有限,有bug在所難免,但是我們這裡是以學習為目的,了解ImageLoader的設計與實現才是我們最重要的目的,一些細節不必在意,可以在你深入的學習過程中修改你認為不合理或者錯誤的地方。如果你有好的實現方法或者有好的建議,也都請指教一二;如果你認為我寫的東西爛得不值一提,那你就深深地埋藏在心裡吧。

基本架構

一般來說,ImageLoader的實現都是基於線程池,在第一版的我也是使用線程池來加載圖片,但是後面的版本卻換成了跟SimpleNet類似的架構模式,原因是覺得線程池剛啟動的時候會稍微慢一些,我感覺不太爽就換了線程模型。當然我也會把線程池的版本在另外的分支上給出,這樣給一些需要的朋友參考。 SimpleImageLoader的基本結構如圖1所示。

圖1

看到這幅圖看過SimpleNet網絡框架的朋友應該是會熟悉一些,基本結構與SimpleNet很相似,其實主要也是我們比較喜歡把架構圖畫成這種分層樣式,感覺比較好理解,

SimpleImageLoader類是用戶的入口,用戶在通過配置類初始化SimpleImageLoader之後就可以向SimpleImageLoader提交加載圖片的請求了。SimpleImageLoader內部維護了一個請求隊列,用戶提交的加載圖片的請求會在內部被封裝成BitmapRequest對象,然後將這些對象放到請求隊列中。在創建隊列時會創建用戶指定數量(默認為CPU個數 + 1)的線程來加載圖片,這些線程在內部命名為RequestDispatcher,它們在run函數中不斷地獲取隊列中的加載請求,然後交給對應的Loader加載圖片。

為了方便用戶的擴展,我們引入了Loader這個抽象,因為在SimpleImageLoader中只支持兩種圖片uri的加載,即網絡圖片uri和本地文件的uri。網絡圖片一般以”http://”或者”https://”開頭,而本地圖片的uri格式卻是”file://”開頭,SimpleImageLoader內部通過圖片uri的格式的不同使用不同的Loader來加載圖片,這樣後續用戶就可以注冊Loader來實現其他格式的加載,例如”drawable:// + 圖片名”來加載res/drawable中的圖片等。這樣保證了SimpleImageLoader可加載圖片uri格式的可擴展性。Loader會通過LoaderManager來進行管理,如果需要注冊自己的Loader實現,則調用LoaderManager的register函數即可。如果你傳遞進去的圖片uri是無效,例如格式錯誤,那麼LoaderManager會返回一個默認的Loader,這個默認的Loader名為NullLoader,它其實什麼也不做,只是為了防止在外部進行判空而已,這種模式成為Null Object設計模式。當然,在加載圖片之前我們會從緩存中讀取,如果有緩存我們則不加載。

Loader加載完圖片之後會先更新UI,即將圖片顯示到對應的ImageView上,在構造BitmapRequest時內部已經將圖片的uri設置為ImageView的tag了。圖片加載完成後判斷ImageView的tag和uri是否相等,如果相等則將圖片顯示到ImageView上,否則不更新ImageView。這一步很重要,很多朋友在使用ImageLoader時出現問題基本上就是由於沒有設置ImageView的tag。

加載圖片的先後順序是由加載策略決定的,策略相關的內容沒有在架構圖中給出。加載策略決定了請求在隊列中的排序,在將請求添加到隊列中時會給每個請求設置一個序號,隊列將根據這個序號對請求進行排序。這樣我們就可以知道哪個請求是先添加進來的,也可以很方便的實現自己的策略類來定制自己的加載策略,比如最後加載到隊列中的請求最先加載。比如我們在ListView滾動時,最後添加到隊列中的圖片請求應該是我們最急需顯示的,我們它們就在手機的當前屏幕,而前面的請求對應的ImageView已經被復用,即使它們加載完成它們也不會被顯示,因為ImageView的tag已經變化了。因此,策略的靈活性依然很重要。

在加載完圖片並且更新UI之後,我們會將圖片緩存起來。內置的緩存類型有四種,無緩存、內存緩存、sd卡緩存、內存和sd卡的雙緩存,這四種緩存都實現了Cache接口,如果你這四種緩存類型還不能滿足你的需求,那麼你可以實現Cache接口,然後實現自己的緩存邏輯,然後在配置ImageLoader時設置需要的緩存類型(具體配置後續說明),如果不配置則默認使用的是內存緩存。這裡我們又看到了一個面向接口編程的例子,即SimpleImageLoader只依賴於Cache接口的抽象,而不是說依賴於某個具體的緩存類,這樣用戶就可以很方面的實現自己的緩存邏輯,並且將緩存實現注入到sdk中。當然,上述的Loader、加載策略實現也是基於同樣的理論基礎,就是說過很多遍的“面向接口編程”。

恩,是時候捋一捋這個執行流程了。

用戶調用displayImage請求加載圖片,SimpleImageLoader將這個加載圖片請求封裝成一個Request,然後加入到隊列中。幾個色瞇瞇的調度子線程不斷地從隊列中獲取請求,然後根據uri的格式獲取到對應的Loader來加載圖片。在加載圖片之前首先會查看緩存中是否含有目標圖片(具體細節在後續的博客再細說),如果有緩存則使用緩存,否則加載目標圖片。獲取到圖片之後,我們會將圖片投遞給ImageView進行更新,如果該ImageView的tag與圖片的uri是一樣的,那麼則更新ImageView,否則不處理。使用ImageView的tag與圖片的uri進行對比是為了防止圖片錯位顯示的問題,這在ImageLoader中是很重要的一步。如果目標圖片沒有緩存,第一次從uri中加載後會加入緩存中,當然從sdcard中加載的圖片我們只會緩存到內存中,而不會再緩存一份到sd卡的另一個目錄中。這樣,整個加載過程也就完成了。

SimpleImageLoader工程結構圖

           

效果圖

上述效果中有四張圖片是顯示不出來的,因為在圖片uri列表中有三張是我手機中的圖片,模擬器中沒有,因此顯示加載失敗。還有一張是無效的uri,也是加載失敗。

Github倉庫地址將在下一篇博客中給出,敬請期待!!

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