Universal-Image-Loader解析(一)基本介紹與使用

Universal-Image-Loader解析系列

Universal-Image-Loader解析(一)基本介紹與使用
Universal-Image-Loader解析(二)內(nèi)部緩存原理
Universal-Image-Loader解析(三)源代碼解析

基本介紹

相信大家平時(shí)做Android應(yīng)用的時(shí)候肥卡,多少會(huì)接觸到異步加載圖片,或者加載大量圖片的問(wèn)題批销,而加載圖片我們常常會(huì)遇到許多的問(wèn)題,比如說(shuō)圖片的錯(cuò)亂蒜哀,OOM等問(wèn)題戳寸,對(duì)于新手來(lái)說(shuō),這些問(wèn)題解決起來(lái)會(huì)比較吃力捂掰,所以就有很多的開(kāi)源圖片加載框架應(yīng)運(yùn)而生贝椿,比較著名的就是Universal-Image-Loader想括,相信很多朋友都聽(tīng)過(guò)或者使用過(guò)這個(gè)強(qiáng)大的圖片加載框架,今天這篇文章就是對(duì)這個(gè)框架的基本介紹以及使用烙博,主要是幫助那些沒(méi)有使用過(guò)這個(gè)框架的朋友們瑟蜈。該項(xiàng)目存在于Github上面Android-Universal-Image-Loader,我們可以先看看這個(gè)開(kāi)源庫(kù)存在哪些特征

  • 多線程下載圖片渣窜,圖片可以來(lái)源于網(wǎng)絡(luò)踪栋,文件系統(tǒng),項(xiàng)目文件夾assets中以及drawable中等

  • 支持隨意的配置ImageLoader图毕,例如線程池,圖片下載器眷唉,內(nèi)存緩存策略予颤,硬盤(pán)緩存策略,圖片顯示選項(xiàng)以及其他的一些配置

  • 支持圖片的內(nèi)存緩存冬阳,文件系統(tǒng)緩存或者SD卡緩存

  • 支持圖片下載過(guò)程的監(jiān)聽(tīng)

  • 根據(jù)控件(ImageView)的大小對(duì)Bitmap進(jìn)行裁剪蛤虐,減少Bitmap占用過(guò)多的內(nèi)存

  • 較好的控制圖片的加載過(guò)程,例如暫停圖片加載肝陪,重新開(kāi)始加載圖片驳庭,一般使用在 ListView,GridView中,滑動(dòng)過(guò)程中暫停加載圖片氯窍,停止滑動(dòng)的時(shí)候去加載圖片

  • 提供在較慢的網(wǎng)絡(luò)下對(duì)圖片進(jìn)行加載

當(dāng)然上面列舉的特性可能不全饲常,要想了解一些其他的特性只能通過(guò)我們的使用慢慢去發(fā)現(xiàn)了

ImageLoaderConfiguration

圖片加載器ImageLoader的配置參數(shù),使用Builder模式狼讨。
常用的配置屬性有

//通過(guò)StorageUtils獲取內(nèi)置的內(nèi)存目錄/data/data/.../cache
File cacheDir = StorageUtils.getCacheDirectory(context);  
ImageLoaderConfiguration config = new ImageLoaderConfiguration  
                .Builder(getApplicationContext())  
                .memoryCacheExtraOptions(480, 800) //即保存的每個(gè)緩存文件的最大長(zhǎng)寬  
                .threadPoolSize(3) //線程池內(nèi)加載的數(shù)量  
                .threadPriority(Thread.NORM_PRIORITY - 2)  
                //解釋?zhuān)寒?dāng)同一個(gè)Uri獲取不同大小的圖片贝淤,緩存到內(nèi)存時(shí),只緩存一個(gè)政供。默認(rèn)會(huì)緩存多個(gè)不同的大小的相同圖片  
                .denyCacheImageMultipleSizesInMemory()  //拒絕緩存多個(gè)圖片播聪。
                .memoryCache(new WeakMemoryCache()) //緩存策略你可以通過(guò)自己的內(nèi)存緩存實(shí)現(xiàn) 朽基,這里用弱引用,缺點(diǎn)是太容易被回收了离陶,不是很好稼虎!
                .memoryCacheSize(2 * 1024 * 1024) //設(shè)置內(nèi)存緩存的大小 
                .diskCacheSize(50 * 1024 * 1024) //設(shè)置磁盤(pán)緩存大小 50M    
                .diskCacheFileNameGenerator(new Md5FileNameGenerator()) //將保存的時(shí)候的URI名稱(chēng)用MD5 加密  
                .tasksProcessingOrder(QueueProcessingType.LIFO) //設(shè)置圖片下載和顯示的工作隊(duì)列排序  
                .diskCacheFileCount(100) //緩存的文件數(shù)量  
                .diskCache(new UnlimitedDiskCache(cacheDir)) //自定義緩存路徑  
                .defaultDisplayImageOptions(defaultOptions) //顯示圖片的參數(shù),默認(rèn):DisplayImageOptions.createSimple()
                .imageDownloader(new BaseImageDownloader(this, 5 * 1000, 30 * 1000)) // connectTimeout (5 s), readTimeout (30 s)超時(shí)時(shí)間  
                .writeDebugLogs() //打開(kāi)調(diào)試日志
                .build();//開(kāi)始構(gòu)建  
//配置使用
ImageLoader.getInstance().init(configuration);  

可以設(shè)置內(nèi)存緩存招刨,硬盤(pán)緩存的相關(guān)參數(shù)等霎俩。

設(shè)置完相關(guān)的參數(shù)后就可進(jìn)行圖片加載顯示

圖片加載

ImageLader提供了幾個(gè)圖片加載的方法,主要是這幾個(gè)displayImage(), loadImage(),loadImageSync()计济,loadImageSync()方法是同步的茸苇,android4.0有個(gè)特性,網(wǎng)絡(luò)操作不能在主線程沦寂,所以loadImageSync()方法我們就不去使用

loadimage()加載圖片

我們先使用ImageLoader的loadImage()方法來(lái)加載網(wǎng)絡(luò)圖片

final ImageView mImageView = (ImageView) findViewById(R.id.image);  
        String imageUrl = "https://lh6.googleusercontent.com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s1024/A%252520Photographer.jpg";  
          
        ImageLoader.getInstance().loadImage(imageUrl, new ImageLoadingListener() {  
              
            @Override  
            public void onLoadingStarted(String imageUri, View view) {  
                  
            }  
              
            @Override  
            public void onLoadingFailed(String imageUri, View view,  
                    FailReason failReason) {  
                  
            }  
              
            @Override  
            public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {  
                mImageView.setImageBitmap(loadedImage);  
            }  
              
            @Override  
            public void onLoadingCancelled(String imageUri, View view) {  
                  
            }  
        });  

傳入圖片的url和ImageLoaderListener, 在回調(diào)方法onLoadingComplete()中將loadedImage設(shè)置到ImageView上面就行了学密,如果你覺(jué)得傳入ImageLoaderListener太復(fù)雜了,我們可以使用SimpleImageLoadingListener類(lèi)传藏,該類(lèi)提供了ImageLoaderListener接口方法的空實(shí)現(xiàn)腻暮,使用的是缺省適配器模式

final ImageView mImageView = (ImageView) findViewById(R.id.image);  
        String imageUrl = "https://lh6.googleusercontent.com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s1024/A%252520Photographer.jpg";  
          
        ImageLoader.getInstance().loadImage(imageUrl, new SimpleImageLoadingListener(){  
  
            @Override  
            public void onLoadingComplete(String imageUri, View view,  
                    Bitmap loadedImage) {  
                super.onLoadingComplete(imageUri, view, loadedImage);  
                mImageView.setImageBitmap(loadedImage);  
            }  
              
        });  

如果我們要指定圖片的大小該怎么辦呢,這也好辦毯侦,初始化一個(gè)ImageSize對(duì)象哭靖,指定圖片的寬和高,代碼如下

final ImageView mImageView = (ImageView) findViewById(R.id.image);  
        String imageUrl = "https://lh6.googleusercontent.com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s1024/A%252520Photographer.jpg";  
          
        ImageSize mImageSize = new ImageSize(100, 100);  
          
        ImageLoader.getInstance().loadImage(imageUrl, mImageSize, new SimpleImageLoadingListener(){  
  
            @Override  
            public void onLoadingComplete(String imageUri, View view,  
                    Bitmap loadedImage) {  
                super.onLoadingComplete(imageUri, view, loadedImage);  
                mImageView.setImageBitmap(loadedImage);  
            }  
              
        });  

上面只是很簡(jiǎn)單的使用ImageLoader來(lái)加載網(wǎng)絡(luò)圖片侈离,在實(shí)際的開(kāi)發(fā)中试幽,我們并不會(huì)這么使用,那我們平常會(huì)怎么使用呢卦碾?我們會(huì)用到DisplayImageOptions铺坞,他可以配置一些圖片顯示的選項(xiàng),比如圖片在加載中ImageView顯示的圖片洲胖,是否需要使用內(nèi)存緩存济榨,是否需要使用文件緩存等等

DisplayImageOptions

可以配置一些圖片顯示的選項(xiàng),比如圖片在加載中ImageView顯示的圖片绿映,是否需要使用內(nèi)存緩存擒滑,是否需要使用文件緩存等等,可供我們選擇的配置如下

DisplayImageOptions options = new DisplayImageOptions.Builder()  
        .showImageOnLoading(R.drawable.ic_stub) // resource or drawable  
        .showImageForEmptyUri(R.drawable.ic_empty) // resource or drawable  
        .showImageOnFail(R.drawable.ic_error) // resource or drawable  
        .resetViewBeforeLoading(false)  // default  
        .delayBeforeLoading(1000)  
        .cacheInMemory(false) // default  
        .cacheOnDisk(false) // default  
        .preProcessor(...)  
        .postProcessor(...)  
        .extraForDownloader(...)  
        .considerExifParams(false) // default  
        .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // default  
        .bitmapConfig(Bitmap.Config.ARGB_8888) // default  
        .decodingOptions(...)  
        .displayer(new SimpleBitmapDisplayer()) // default  
        .handler(new Handler()) // default  
        .build();  

大家就可以根據(jù)實(shí)際情況去設(shè)置叉弦。

displayImage()加載圖片

接下來(lái)我們就來(lái)看看網(wǎng)絡(luò)圖片加載的另一個(gè)方法displayImage()丐一,代碼如下

        String imageUrl = "https://lh6.googleusercontent.com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s1024/A%252520Photographer.jpg";  
          
        //顯示圖片的配置  
        DisplayImageOptions options = new DisplayImageOptions.Builder()  
                .showImageOnLoading(R.drawable.ic_stub)  
                .showImageOnFail(R.drawable.ic_error)  
                .cacheInMemory(true)  
                .cacheOnDisk(true)  
                .bitmapConfig(Bitmap.Config.RGB_565)  
                .build();  
          
        ImageLoader.getInstance().displayImage(imageUrl, mImageView, options);  

可以看到這里是直接傳遞了ImageView進(jìn)行設(shè)置顯示,并不需要監(jiān)聽(tīng)后設(shè)置淹冰,這樣更為簡(jiǎn)便钝诚,這也是displayImageloadImage的區(qū)別。

加載其他來(lái)源的圖片

使用Universal-Image-Loader框架不僅可以加載網(wǎng)絡(luò)圖片榄棵,還可以加載sd卡中的圖片凝颇,Content provider等潘拱,使用也很簡(jiǎn)單,只是將圖片的url稍加的改變下就行了拧略,下面是加載文件系統(tǒng)的圖片

我們只需要給每個(gè)圖片來(lái)源的地方加上Scheme包裹起來(lái)(Content provider除外)芦岂,然后當(dāng)做圖片的url傳遞到imageLoader中,Universal-Image-Loader框架會(huì)根據(jù)不同的Scheme獲取到輸入流

        //圖片來(lái)源于文件
        String imagePath = "/mnt/sdcard/image.png";  
        String imageUrl = Scheme.FILE.wrap(imagePath);  
        //相當(dāng)于file:/mnt/sdcard/image.png

        //圖片來(lái)源于Content provider  
        String contentprividerUrl = "content://media/external/audio/albumart/13";  
          
        //圖片來(lái)源于assets  
        String assetsUrl = Scheme.ASSETS.wrap("image.png");  
          
        //圖片來(lái)源于  
        String drawableUrl = Scheme.DRAWABLE.wrap("R.drawable.image"); 

獲取到對(duì)應(yīng)URL后就可以調(diào)用display/loadImage方法進(jìn)行顯示垫蛆。

GirdView,ListView加載圖片

相信大部分人都是使用GridView禽最,ListView來(lái)顯示大量的圖片,而當(dāng)我們快速滑動(dòng)GridView袱饭,ListView川无,我們希望能停止圖片的加載,而在GridView虑乖,ListView停止滑動(dòng)的時(shí)候加載當(dāng)前界面的圖片懦趋,這個(gè)框架當(dāng)然也提供這個(gè)功能,使用起來(lái)也很簡(jiǎn)單疹味,它提供了PauseOnScrollListener這個(gè)類(lèi)來(lái)控制ListView,GridView滑動(dòng)過(guò)程中停止去加載圖片仅叫,該類(lèi)使用的是代理模式

listView.setOnScrollListener(new PauseOnScrollListener(imageLoader, pauseOnScroll, pauseOnFling));  

gridView.setOnScrollListener(new PauseOnScrollListener(imageLoader, pauseOnScroll, pauseOnFling));  

第一個(gè)參數(shù)就是我們的圖片加載對(duì)象ImageLoader,
第二個(gè)是控制是否在滑動(dòng)過(guò)程中暫停加載圖片,如果需要暫停傳true就行了糙捺,
第三個(gè)參數(shù)控制猛的滑動(dòng)界面的時(shí)候圖片是否加載

OutOfMemoryError

雖然這個(gè)框架有很好的緩存機(jī)制诫咱,有效的避免了OOM的產(chǎn)生,一般的情況下產(chǎn)生OOM的概率比較小洪灯,但是并不能保證OutOfMemoryError永遠(yuǎn)不發(fā)生坎缭,這個(gè)框架對(duì)于OutOfMemoryError做了簡(jiǎn)單的catch,保證我們的程序遇到OOM而不被crash掉,但是如果我們使用該框架經(jīng)常發(fā)生OOM签钩,我們應(yīng)該怎么去改善呢幻锁?

  • 減少線程池中線程的個(gè)數(shù),在ImageLoaderConfiguration中的(.threadPoolSize)中配置边臼,推薦配置1-5

  • 在DisplayImageOptions選項(xiàng)中配置bitmapConfig為Bitmap.Config.RGB_565,因?yàn)槟J(rèn)是ARGB_8888假消, 使用RGB_565會(huì)比使用ARGB_8888少消耗2倍的內(nèi)存

  • 在ImageLoaderConfiguration中配置圖片的內(nèi)存緩存為memoryCache(new WeakMemoryCache()) 或者不使用內(nèi)存緩存

  • 在DisplayImageOptions選項(xiàng)中設(shè)置.imageScaleType(ImageScaleType.IN_SAMPLE_INT)或者imageScaleType(ImageScaleType.EXACTLY)

參考資料

Android 開(kāi)源框架Universal-Image-Loader完全解析(一)--- 基本介紹及使用
Android-Universal-Image-Loader

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末柠并,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子富拗,更是在濱河造成了極大的恐慌臼予,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,252評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件啃沪,死亡現(xiàn)場(chǎng)離奇詭異粘拾,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)创千,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)缰雇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)入偷,“玉大人,你說(shuō)我怎么就攤上這事械哟∈柚” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,814評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵暇咆,是天一觀的道長(zhǎng)锋爪。 經(jīng)常有香客問(wèn)我,道長(zhǎng)爸业,這世上最難降的妖魔是什么其骄? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,869評(píng)論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮扯旷,結(jié)果婚禮上拯爽,老公的妹妹穿的比我還像新娘。我一直安慰自己薄霜,他們只是感情好某抓,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著惰瓜,像睡著了一般否副。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上崎坊,一...
    開(kāi)封第一講書(shū)人閱讀 52,475評(píng)論 1 312
  • 那天备禀,我揣著相機(jī)與錄音,去河邊找鬼奈揍。 笑死曲尸,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的男翰。 我是一名探鬼主播另患,決...
    沈念sama閱讀 41,010評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蛾绎!你這毒婦竟也來(lái)了昆箕?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,924評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤租冠,失蹤者是張志新(化名)和其女友劉穎鹏倘,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體顽爹,經(jīng)...
    沈念sama閱讀 46,469評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡纤泵,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了镜粤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片捏题。...
    茶點(diǎn)故事閱讀 40,680評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡玻褪,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出涉馅,到底是詐尸還是另有隱情归园,我是刑警寧澤,帶...
    沈念sama閱讀 36,362評(píng)論 5 351
  • 正文 年R本政府宣布稚矿,位于F島的核電站庸诱,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏晤揣。R本人自食惡果不足惜桥爽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望昧识。 院中可真熱鬧钠四,春花似錦、人聲如沸跪楞。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,519評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)甸祭。三九已至缕碎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間池户,已是汗流浹背咏雌。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,621評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留校焦,地道東北人赊抖。 一個(gè)月前我還...
    沈念sama閱讀 49,099評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像寨典,于是被迫代替她去往敵國(guó)和親氛雪。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容