目錄
從零實(shí)現(xiàn)ImageLoader(一)—— 架構(gòu)
從零實(shí)現(xiàn)ImageLoader(二)—— 基本實(shí)現(xiàn)
從零實(shí)現(xiàn)ImageLoader(三)—— 線程池詳解
從零實(shí)現(xiàn)ImageLoader(四)—— Handler的內(nèi)心獨(dú)白
從零實(shí)現(xiàn)ImageLoader(五)—— 內(nèi)存緩存LruCache
從零實(shí)現(xiàn)ImageLoader(六)—— 磁盤緩存DiskLruCache
前言
眾所周知,由于移動設(shè)備的特殊性,圖片加載一直是Android知識體系里的重點(diǎn)。由于網(wǎng)絡(luò)的限制,我們需要對圖片進(jìn)行緩存,避免無謂的流量消耗。由于內(nèi)存的限制,我們又需要對圖片進(jìn)行縮放,防止觸發(fā)OOM。這些都是一個(gè)優(yōu)秀的圖片加載框架所需要考慮的。
Android發(fā)展到現(xiàn)在,各種圖片加載框架也是層出不群。從剛開始的Android-Universal-Image-Loader,到后來Google推出的Volley,再到現(xiàn)在的Fresco,Picasso,Glide百花齊放,總有一款適合你。
可是,身為一個(gè)優(yōu)秀的程序員我們不應(yīng)該只滿足于使用別人已經(jīng)寫好的框架,也有必要對其中的知識點(diǎn)深入理解。這次的系列文章就是從實(shí)現(xiàn)一個(gè)圖片加載框架開始,對其中碰到的問題加以突破,之后再對目前的幾個(gè)圖片加載框架加以分析,領(lǐng)略優(yōu)秀的框架所包含的設(shè)計(jì)理念。
預(yù)期效果
在開始之前我們先看一下我們將要實(shí)現(xiàn)的代碼效果:
ImageLoader.with(this).load(URL).into(imageView);
沒錯(cuò),就只有短短這么一行代碼。熟悉Picasso或者Glide的同學(xué)想必已經(jīng)發(fā)現(xiàn)了,這不就是Picasso的調(diào)用方式嗎?之所以選擇這種鏈?zhǔn)降恼{(diào)用方式就是由于他可以做到極簡,這也是Picasso和Glide之所以如此受歡迎的原因之一。

架構(gòu)
接下來我們看一下ImageLoader的架構(gòu)圖:

這次我們只實(shí)現(xiàn)網(wǎng)絡(luò)數(shù)據(jù)的加載,通過ImageLoader類的load(String url)方法進(jìn)行處理。而本地圖片、項(xiàng)目資源圖片等等其他數(shù)據(jù)的加載都大同小異,就不再涉及了。
加載方式我們實(shí)現(xiàn)了同步加載和異步加載,分別由Dispatcher類的get()方法和into(ImageView imageView)方法給出。這里就牽扯到了線程池的使用,線程間通信等知識。
當(dāng)然也少不了基本上每個(gè)圖片加載框架都有的內(nèi)存緩存和磁盤緩存,我們這次分別選擇了LruCache類和Jake Wharton大神的DiskLruCache類,后面也會對這兩個(gè)類的源碼進(jìn)行深入的分析。
緩存
下面詳細(xì)介紹一下緩存策略的實(shí)現(xiàn):
為什么要使用緩存
在介紹緩存策略之前,我們先來回答一個(gè)問題:為什么要使用緩存?
移動設(shè)備在使用網(wǎng)絡(luò)時(shí)往往面臨一個(gè)問題,那就是流量是需要收費(fèi)的,這就需要軟件開發(fā)者在開發(fā)時(shí)應(yīng)當(dāng)盡量避免流量的消耗,而流量消耗的大頭就是圖片。這時(shí)候本地緩存就是一個(gè)很好的解決方式。而且移動設(shè)備用戶所處的網(wǎng)絡(luò)環(huán)境也是不可知的,如果用戶處于弱網(wǎng)絡(luò)環(huán)境下,那圖片加載所要消耗的時(shí)間將是不可忍受的,這也是使用本地緩存的原因之一。
同時(shí),移動設(shè)備的內(nèi)存是有限的,如果一個(gè)應(yīng)用包含大量的圖片,全部放到內(nèi)存中必然會觸發(fā)OOM,可如果每次都要重新從本次磁盤加載的話,性能就會有很大的消耗。而且本地加載雖然比網(wǎng)絡(luò)要快但也是需要時(shí)間的,這也往往造成界面的卡頓。這時(shí)候一個(gè)好的內(nèi)存緩存策略就是不可或缺的。
緩存原理
明白了為什么使用,接下來就要考慮怎么實(shí)現(xiàn)了。大家先看一張圖,這是我仿照Android-Universal-Image-Loader的圖片加載流程圖畫的:

一圖勝千言,相信這張圖片已經(jīng)很能說明問題了。
首先,程序會在內(nèi)存緩存中查找Bitmap,如果命中則直接顯示,如果沒有就會去本地磁盤緩存中查找緩存文件;如果在磁盤緩存中命中就將緩存文件轉(zhuǎn)換為Bitmap再進(jìn)行顯示,這個(gè)過程中會將Bitmap加入內(nèi)存緩存中;如果本地磁盤中沒有就會從網(wǎng)絡(luò)上進(jìn)行下載,并且緩存在磁盤和內(nèi)存中。
總結(jié)
這篇文章對ImageLoader的架構(gòu)已經(jīng)介紹完畢,接下來就要開始具體的實(shí)現(xiàn)了,敬請期待。