從設計到實現,一步步教你實現Android-Universal-ImageLoader-輔助類

來源:互聯網
上載者:User

標籤:listener   strong   知識   枚舉類   http   mil   unit   關鍵字   add   

通過前面幾篇博文。我們分析了 AUI 的緩衝、工具類、顯示與載入這幾個方面的代碼。今天呢,我們繼續研究 AUI 的原始碼,學習當中的核心協助工具輔助類。

希望大家能在裡面學到東西哈。

Download

要下載一張圖片,我們想象須要什麼哈:首先我們得設定支援的協議。得有下載的連結。由對應的下載連結去下載圖片。進而得到圖片的輸入資料流,剩下的就交給圖片的顯示/載入類處理啦。

那麼我們能夠設計出以下的介面:

public interface ImageDownloader {    InputStream getStream(String imageUri, Object extra) throws IOException;    public enum Scheme {        HTTP("http"), HTTPS("https"), FILE("file"), CONTENT("content"), ASSETS("assets"), DRAWABLE("drawable"), UNKNOWN("");        private String scheme;        private String uriPrefix;        Scheme(String scheme) {            this.scheme = scheme;            uriPrefix = scheme + "://";        }        public static Scheme ofUri(String uri) {            if (uri != null) {                for (Scheme s : values()) {                    if (s.belongsTo(uri)) {                        return s;                    }                }            }            return UNKNOWN;        }        private boolean belongsTo(String uri) {            return uri.toLowerCase(Locale.US).startsWith(uriPrefix);        }        public String wrap(String path) {            return uriPrefix + path;        }        public String crop(String uri) {            if (!belongsTo(uri)) {                throw new IllegalArgumentException(String.format("URI [%1$s] doesn‘t have expected scheme [%2$s]", uri, scheme));            }            return uri.substring(uriPrefix.length());        }    }}

看到這裡大家可能會疑惑了,我們不是設計介面麼,為啥要搞個枚舉類型,並且還在裡面搞那麼多亂七八糟的東西……事實上。假設大家有看過《Thinking In Java》的話就會知道。在 Java 中,enum 實際上就是一個類。由於 enum 定義後的枚舉類在編譯時間預設繼承 java.lang.Enum 類。而該枚舉類會自己主動被加上 final 關鍵字修飾。這也使得枚舉類無法被繼承。更詳細的解釋大家能夠自行 Google 哈。

那麼為什麼要在 ImageDownloader 裡引入這個枚舉類呢?我們最好還是先看看枚舉類內究竟有什麼。在枚舉類 Scheme 中,主要有四個方法,而這四個方法都用於處理 Uri,如:裁減 Uri、加入 Uri 首碼、推斷 Uri。也就是說,Scheme 的抽象職責是:對 Uri 進行修飾。

而 Scheme 對 Uri 的修飾結果將交給 ImageDownloader 完畢下載操作。

換言之,Scheme 的抽象與 ImageDownloader 的抽象實際上是不一致的(ImageDownloader 的抽象是下載圖片,而下載圖片所需的 Uri 須要進行什麼處理才幹被 ImageDownloader 使用,並完畢下載事實上不重要),為了讓減少類的耦合度,我們在 ImageDownloader 的內部實現了 Scheme 類。

那麼有人可能會問了,那我們另外建立一個類不行嗎?就我的理解來看,肯定是能夠的。由於 Scheme 本質上也是一個類,我們新建立一個類。聲明為 final 類。加入對應的靜態常量、方法。事實上效果也是一樣的。

那作者為什麼要這麼幹呢?看過《Effective Java》的朋友可能會知道,實現單例的最佳方法就是使用 enum,詳細的解釋大家自己去查吧。我就不在這裡多說了。

那麼作者在這裡實際上就是在介面內部定義了一個單例。

What is an efficient way to implement a singleton pattern in Java?

BaseImageDownloader 實現了 ImageDownloader 介面,並且依據我們的需求實現了對應的圖片下載細節,詳細沒什麼好解說的,大家能夠自行閱讀原始碼哈~

Listener

在 AUI 中,實際上須要用到的 Listener 並不多,畢竟圖片載入僅僅是一個非常小的功能模組嘛。那麼 AUI 究竟包括了什麼 Listener 呢?

  • 圖片載入監聽器:監聽圖片載入的開始、結束、失敗、取消
  • 圖片載入進度監聽器:監聽圖片載入的進度
  • 圖片載入滾動監聽器:當圖片載入進行中,若發生滾動,則停止載入,換言之,僅僅載入當前螢幕顯示的圖片。圖片滾動過程的圖片則不載入。

可能有人會認為非常奇怪。為什麼圖片載入監聽器和圖片載入進度監聽器要分開實現。事實上我也想不懂。希望有人能給我個解釋……

Assist

在 assist 裡面有幾個類我們在之前的博文中已經有提過了,我就不再這反覆拉。

比較簡單的類我也會一筆帶過。希望大家理解哈。

deque

在這裡面都是一些雙端隊列。比如 LinkedBlockingDeque、LIFOLinkedBlockingDeque。雙端隊列的對應知識。以及詳細實現我相信不用我在這裡廢話了,畢竟資料結構的課程中一定會說到這個知識點,這也是個主要的、必須掌握的資料結構。

那麼在這裡我們須要瞭解什麼呢?那就是:為什麼引入雙端隊列作為 AUI 的資料結構,雙端隊列較之其它資料結構在這個應用情境下有什麼長處。

我們最好還是先看看 Deque 在哪裡被用到吧,在 AUI 庫中搜尋發現。DefaultConfigurationFactory 調用了 Deque。

那麼 DefaultConfigurationFactory 究竟是什麼呢?

從該類的命名以及內部的方法名我們能夠知道。DefaultConfigurationFactory 就是 AUI 預設的配置工廠類,假設開發人員沒有自己定義對應的配置選項的話,AUI 就會使用這個類所設定的預設選項,完畢對應的載入、下載、緩衝等等……

最好還是看看以下的程式碼片段:

    public static Executor createExecutor(int threadPoolSize, int threadPriority,            QueueProcessingType tasksProcessingType) {        boolean lifo = tasksProcessingType == QueueProcessingType.LIFO;        BlockingQueue<Runnable> taskQueue =                lifo ? new LIFOLinkedBlockingDeque<Runnable>() : new LinkedBlockingQueue<Runnable>();        return new ThreadPoolExecutor(threadPoolSize, threadPoolSize, 0L, TimeUnit.MILLISECONDS, taskQueue,                createThreadFactory(threadPriority, "uil-pool-"));    }

在這段代碼中。我們會獲得線程池,並且用 LIFOLinkedBlockingDeque 作為線程的處理隊列。也就是說,在 AUI 庫中。雙端隊列這個資料結構是用來完畢 AUI 線程處理的。那麼為什麼要選擇雙端隊列,為什麼又選擇 LIFOLinkedBlockingDeque 作為預設選項呢?

之所以選擇雙端隊列。是由於 ThreadPoolExecutor 使用的是生產者-消費者模式,在 ThreadPoolExecutor 類內部使用 BlockingQueue 作為任務處理隊列能滿足生產者-消費者模式對任務儲存資料結構的要求。而在我們的 assist 中。LIFOLinkedBlockingDeque 是 LinkedBlockingDeque 的子類。而 LinkedBlockingDeque 實現了 BlockingDeque 介面,BlockingDeque 介面又繼承於 BlockingQueue。

Others

在 assist 中剩下的輔助類我認為都挺簡單的,都是一些基本 API 呼叫的簡化。大家自己看看原始碼都能看懂的~

從設計到實現,一步步教你實現Android-Universal-ImageLoader-輔助類

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.