站在用戶的角度思考問題,與客戶深入溝通,找到華龍網(wǎng)站設(shè)計與華龍網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗,讓設(shè)計與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個性化、用戶體驗好的作品,建站類型包括:網(wǎng)站設(shè)計制作、做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、域名注冊、網(wǎng)站空間、企業(yè)郵箱。業(yè)務(wù)覆蓋華龍地區(qū)。
ImageLoader的工作原理:在顯示圖片的時,它會先在內(nèi)存中查找,如果沒有就去本地查找,如果還沒有,就開一個新的線程去下載這張圖片,下載成功會把圖片同時緩存在內(nèi)存和本地。
我們在基于這個原理,在每次退出一個頁面時候,把ImageLoader內(nèi)存中緩存全部清除,這樣就節(jié)省了大量內(nèi)存,反正下次再用到的時候從本地再取出來就行了。需要說明的是,由于ImageLoader對圖片是軟引用的形式,所以在內(nèi)存中的圖片會存在內(nèi)存不足的時候被系統(tǒng)回收。
總設(shè)計圖:
ImageLoader由三大組件組成:
ImagaLoaderConfiguaration——對圖片緩存進(jìn)行總體配置,包含內(nèi)存緩存的大小,本地緩存的大小和位置、日志、下載策略(FIFO還是LIFO)等。
ImageLoader——一般使用displayImage來把URL對應(yīng)的圖片顯示在ImageView上。
DisplayImageOptions——在每個頁面需要顯示圖片的地方,控制如何顯示的細(xì)節(jié),比如指定下載時的默認(rèn)圖、是否將緩存放到內(nèi)存或本地磁盤。
從三者的協(xié)作關(guān)系上看,他們有點像廚房規(guī)定、廚師、客戶個人口味之間的關(guān)系。ImageLoaderConfiguration就像是廚房里面的規(guī)定,每一個廚師要怎么著裝,要怎么保持廚房的干凈,這是針對每一個廚師都適用的規(guī)定,而且不允許個性化改變。ImageLoader就像是具體做菜的廚師,負(fù)責(zé)具體菜譜的制作。DisplayImageOptions就像每個客戶的偏好,根據(jù)客戶是重口味還是清淡,每一個p_w_picpathLoader根據(jù)DisplayImageOptions的要求具體執(zhí)行。
示例代碼:
// DON'T COPY THIS CODE TO YOUR PROJECT! This is just example of ALL options using.// See the sample project how to use ImageLoader correctly.File cacheDir =StorageUtils.getCacheDirectory(context);ImageLoaderConfiguration config =newImageLoaderConfiguration.Builder(context) .memoryCacheExtraOptions(480, 800) // default = device screen dimensions .diskCacheExtraOptions(480, 800, null) .taskExecutor(...) .taskExecutorForCachedImages(...) .threadPoolSize(3) // default .threadPriority(Thread.NORM_PRIORITY-2) // default .tasksProcessingOrder(QueueProcessingType.FIFO) // default .denyCacheImageMultipleSizesInMemory() .memoryCache(newLruMemoryCache(2*1024*1024)) .memoryCacheSize(2*1024*1024) .memoryCacheSizePercentage(13) // default .diskCache(newUnlimitedDiskCache(cacheDir)) // default .diskCacheSize(50*1024*1024) .diskCacheFileCount(100) .diskCacheFileNameGenerator(newHashCodeFileNameGenerator()) // default .p_w_picpathDownloader(newBaseImageDownloader(context)) // default .p_w_picpathDecoder(newBaseImageDecoder()) // default .defaultDisplayImageOptions(DisplayImageOptions.createSimple()) // default .writeDebugLogs() .build();
可以看到ImagaLoaderConfiguaration的職責(zé)就是記錄相關(guān)的配置,它的內(nèi)部就是一些字段的集合。
每一個ImageLoader.displayImage(...)都可以使用DisplayImageOptions,具體配置代碼如下:
// DON'T COPY THIS CODE TO YOUR PROJECT! This is just example of ALL options using.// See the sample project how to use ImageLoader correctly.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 .p_w_picpathScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // default .bitmapConfig(Bitmap.Config.ARGB_8888) // default .decodingOptions(...) .displayer(new SimpleBitmapDisplayer()) // default .handler(new Handler()) // default .build();
最終使用時候,簡單幾句就行了,傳入一個ImageView控件
ImageLoader p_w_picpathLoader = ImageLoader.getInstance(); // Get singleton instance// Load p_w_picpath, decode it to Bitmap and display Bitmap in ImageView (or any other view // which implements ImageAware interface)p_w_picpathLoader.displayImage(p_w_picpathUri, p_w_picpathView);
又或者直接
// Load p_w_picpath, decode it to Bitmap and return Bitmap to callbackp_w_picpathLoader.loadImage(p_w_picpathUri, new SimpleImageLoadingListener() { @Override public void onLoadingComplete(String p_w_picpathUri, View view, Bitmap loadedImage) { // Do whatever you want with Bitmap } });
盡管ImageLoader很強(qiáng)大,但一直把圖片緩存在內(nèi)存中,會導(dǎo)致內(nèi)存占用過高。雖然對圖片的引用是軟引用,軟引用在內(nèi)存不夠的時候會被GC,但我們還是希望減少GC的次數(shù),所以要經(jīng)常手動清理ImageLoader中的緩存。
比如,我們經(jīng)常在做項目的時候,會有一個AppBaseActivity的基類,這樣我們可以在基類的onDestroy方法中,執(zhí)行ImageLoader的clearMemoryCache方法,以確保頁面銷毀時,把為了顯示這個頁面而增加的內(nèi)存緩存清除,這樣即使到了下個頁面要復(fù)用之前加載過的圖片,雖然內(nèi)存沒有了,根據(jù)ImageLoader的緩存策略,在本地磁盤上還是能被找到的。
比如:
protected void onDestroy() { //回收該頁面緩存在內(nèi)存的圖片 p_w_picpathLoader.clearMemoryCache(); super.onDestroy(); }
簡介:
Fresco 是一個強(qiáng)大的圖片加載組件。它是Facebook開源的圖片加載庫
Fresco 中設(shè)計有一個叫做 p_w_picpath pipeline 的模塊。它負(fù)責(zé)從網(wǎng)絡(luò),從本地文件系統(tǒng),本地資源加載圖片。為了最大限度節(jié)省空間和CPU時間,它含有3級緩存設(shè)計(2級內(nèi)存,1級文件)。
Fresco 中設(shè)計有一個叫做 Drawees 模塊,方便地顯示loading圖,當(dāng)圖片不再顯示在屏幕上時,及時地釋放內(nèi)存和空間占用。
Fresco 支持 Android2.3(API level 9) 及其以上系統(tǒng)。
流程圖:
原理:
Fresco 設(shè)計了p_w_picpath pipeline 的概念,它負(fù)責(zé)先后檢查內(nèi)存,磁盤文件,如果都沒有再老老實實從網(wǎng)絡(luò)下載圖片。
主要有個三層緩存的概念
第一層:Bitmap緩存
在Android 5.0系統(tǒng)中,考慮到內(nèi)存管理有了很大改進(jìn),所以 Bitmap緩存位于Java的heap中,而在Android 4.X或更低的系統(tǒng)中,Bitmap緩存位于ashmem中,而不是位于Java的heap中,這意味著圖片的創(chuàng)建和回收不會引發(fā)過多的GC,從而讓APP運行的更快。
第二層:內(nèi)存緩存
內(nèi)存緩存中存儲了圖片的原始壓縮格式,從內(nèi)存緩存中取出的圖片,在顯示前必須先解碼,當(dāng)APP切換到后臺時,內(nèi)存緩存也會被清空。
第三層:磁盤緩存
又名本地緩存,磁盤緩存中存儲的也是圖片的原始壓縮格式,在使用前也要先解碼,當(dāng)APP切換到后臺時,磁盤緩存不會丟失,即使關(guān)機(jī)也不會。
使用:
為了下載網(wǎng)絡(luò)圖片,請確保在 AndroidManifest.xml
中有以下權(quán)限:
在 Application 初始化時,在應(yīng)用調(diào)用 setContentView()
之前,進(jìn)行初始化:
Fresco.initialize(context);
在xml布局文件中, 加入命名空間:
加入SimpleDraweeView:
開始加載圖片
Uri uri = Uri.parse("https://raw.githubusercontent.com/facebook/fresco/gh-pages/static/fresco-logo.png"); SimpleDraweeView draweeView = (SimpleDraweeView) findViewById(R.id.my_p_w_picpath_view); draweeView.setImageURI(uri);
我們這里說的圖片,是根據(jù)服務(wù)端的接口返回的圖片URL地址開啟一個線程下載到APP本地并顯示的,很多APP崩潰的原因就是圖片的問題沒處理好。那么就有一些相關(guān)解決方案策略,如下。
要確保下載的每張圖,都符合ImageView控件的大小??梢允孪葴?zhǔn)備很多套不同的分辨率的圖片,然后每次根據(jù)URL請求圖片時,都要額外在URL上加兩個參數(shù),width和height,從而要求服務(wù)器返回其中某一個張圖,比如:http://www.aaa.com/a.png?width=100&height=50
低流量模式。在2G和3G網(wǎng)絡(luò)環(huán)境下,我們應(yīng)該適當(dāng)降低圖片的質(zhì)量,降低圖片質(zhì)量,相應(yīng)的圖片大小也會降低,簡稱低流量模式,比如在請求網(wǎng)址中再添加一個參數(shù),叫做quality,在2G網(wǎng)絡(luò)下這個值為50%,在3G網(wǎng)絡(luò)情況下,這個值為70%,這樣就會將JPG圖片質(zhì)量降低為50%或70%。
極速模式。發(fā)現(xiàn)在2G和3G網(wǎng)絡(luò)環(huán)境下,大部分用戶對圖片不感興趣,我們可以設(shè)計一些只有文字的頁面,這種頁面稱呼為極速模式,以節(jié)省流量。
本篇主要介紹了第三方圖片加載庫的原理和使用方法,特別是ImageLoader的介紹,因為圖片顯示在APP中是很常見的應(yīng)用場景,況且ImageLoader已經(jīng)封裝好了一些類和方法。我們可以直接拿來用了。而不用重復(fù)去寫了。如果自己去寫一個的話,這方面的程序還是比較麻煩的,要考慮多線程緩存,內(nèi)存溢出等很多方面,再說這么多程序都在用,說明穩(wěn)定性還是可靠的,類似這種工具類能用穩(wěn)定成熟的,我們作為一名開發(fā)人員,專注度還是在應(yīng)用業(yè)務(wù)開發(fā)上。