Glide Picasso Fresco UIL 圖片框架 緩存 MD


Markdown版本筆記 我的GitHub首頁 我的博客 我的微信 我的郵箱
MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina.com

Glide Picasso Fresco UIL 圖片框架 MD


目錄

Glide Google推薦 24k

Glide 官方文檔
Glide 英文教程
Glide 中文教程

簡介

我們要曉得:Glide是Google推薦的圖片加載庫,專注於流暢的滾動

Glide 是 Google 一位員工的大作,他完全是基於 Picasso 的,沿襲了 Picasso 的簡潔風格,但是在此做了大量優化與改進。

Glide 默認的 Bitmap 格式是 RGB_565 格式,而 Picasso 默認的是 ARGB_8888 格式,相比而言,這個內存開銷要小一半。

在磁盤緩存方面,Picasso 只會緩存原始尺寸的圖片,而 Glide 緩存的是多種規格,也就意味着 Glide 會根據你 ImageView 的大小來緩存相應大小的圖片尺寸,比如你 ImageView 大小是 200*200,原圖是 400*400 ,而使用 Glide 就會緩存 200*200 規格的圖,而 Picasso 只會緩存 400*400 規格的。這個改進就會導致 Glide 比 Picasso 加載的速度要快,畢竟少了每次裁剪重新渲染的過程。

最重要的一個特性是 Glide 支持加載 Gif 動態圖,而 Picasso 不支持該特性。

除此之外,還有很多其他配置選項的增加。

總體來說,Glide 是在 Picasso 基礎之上進行的二次開發,各個方面做了不少改進,不過這也導致他的包比 Picasso 大不少,不過也就不到 500k,Picasso 是100多k,方法數也比 Picasso 多不少,不過畢竟級別還是蠻小的,影響不是很大。

GitHub 上的介紹

An image loading and caching library for Android focused on smooth scrolling

Glide is a fast and efficient open source media management and image loading framework for Android that wraps media decoding, memory and disk caching, and resource pooling into a simple and easy to use interface.

Glide supports fetching, decoding, and displaying video stills, images, and animated GIFs. Glide includes a flexible API that allows developers to plug in to almost any network stack. By default Glide uses a custom HttpUrlConnection based stack, but also includes utility libraries plug in to Google's Volley project or Square's OkHttp library instead.

Glide's primary首要的 focus is on making scrolling any kind of a list of images as smooth and fast as possible, but Glide is also effective for almost any case where you need to fetch, resize, and display a remote image.

基本使用

添加依賴:

repositories {
  mavenCentral()
  google()
}

dependencies {
  implementation 'com.github.bumptech.glide:glide:4.8.0'
  annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'
}

加載圖片:

Glide.with(context)
    .load("http://inthecheesefactory.com/uploads/source/glidepicasso/cover.jpg")
    .into(ivImg);

Glide的 with 方法不光接受 Context,還接受 Activity 和 Fragment。
同時將 Activity/Fragment 作為 with() 參數的好處是:圖片加載會和 Activity/Fragment 的生命周期保持一致,比如在 Paused 狀態暫停加載,在 Resumed 的時候又自動重新加載。所以我建議傳參的時候傳遞 Activity 和 Fragment 給Glide,而不是 Context。
當然,如果使用 Application 作為上下文,Glide 請求將不受 Activity/Fragment 生命周期控制。

總結

  • 優點:加載速度極快,框架體積小,四五百KB
  • 缺點:因為機制的選擇不同,速度快了,但是圖片質量低了,RGB565
  • 特點:根據ImageView大小來進行緩存,也就是說一張圖片可能根據展示情況來緩存不同尺寸的幾份

可以 load 的資源類型

Glide基本可以load任何可以拿到的媒體資源,如:

load(String string)
load SD卡資源:load("file://"+ Environment.getExternalStorageDirectory().getPath()+"/test.jpg") 
load assets資源:load("file:///android_asset/f003.gif") 
load raw資源:load("Android.resource://com.frank.glide/raw/raw_1")
          或 load("android.resource://com.frank.glide/raw/"+R.raw.raw_1) 
load drawable資源:load("android.resource://com.frank.glide/drawable/news")
               或 load("android.resource://com.frank.glide/drawable/"+R.drawable.news) 
load ContentProvider資源:load("content://media/external/images/media/139469") 
load http資源:load("http://img.my.csdn.net/uploads/201508/05/1438760757_3588.jpg") 
load https資源:load("https://img.alicdn.com/tps/TB1uyhoMpXXXXcLXVXXXXXXXXXX-476-538.jpg_240x5000q50.jpg_.webp") 

當然,load不限於String類型,還可以:

  • load(File file) file:The File containing the image。這個文件可能不存在於你的設備中,然而你可以用任何文件路徑,去指定一個圖片路徑。
  • load(Integer resourceId) resourceId:the id of the resource containing the image。可以用R.drawable或R.mipmap
  • load(Uri uri) uri:The Uri representing the image. Must be of a type handled by UriLoader
  • load(byte[] model) model:the data to load.
  • loadFromMediaStore(Uri uri) uri:The uri representing the media.
  • load(T model) model:The model the load.
  • load(URL url):deprecated

load的資源也可以是本地視頻,但如果是一個網絡 URL 的視頻,它是不工作的!

從資源 id 轉換成 Uri 的方法:

public static Uri resourceIdToUri(Context context, int resourceId) {
    return Uri.parse("android.resource://" + context.getPackageName() + "/" + resourceId);
}

Glide 緩存策略

官方文檔

本文主要介紹了如何配置和管理Glide中的緩存(內存緩存和磁盤緩存),其中大部分內容都可以直接在官方Wiki中找到,這里只是進行了整理和匯總。

Picasso 和 Glide 在磁盤緩存策略上有很大的不同。Picasso 緩存的是一個全尺寸的圖片,而 Glide 緩存的是跟 ImageView 尺寸相同的圖片,而且如果加載的是 RGB565 圖片,那么緩存中的圖片也是 RGB565。

Picasso 只緩存一個全尺寸的。而 Glide 則不同,它會為每種大小的 ImageView 緩存 一次。盡管一張圖片已經緩存了一次,但是假如你要在另外一個地方再次以不同尺寸顯示,需要重新下載,調整成新尺寸的大小,然后將這個尺寸的也緩存起來。

不過,你可以改變這種行為,讓Glide既緩存全尺寸又緩存其他尺寸:

Glide.with(this)
     .load("http://nuuneoi.com/uploads/source/playstore/cover.jpg")
     .diskCacheStrategy(DiskCacheStrategy.ALL)
     .into(ivImgGlide);

下次在任何 ImageView 中加載圖片的時候,全尺寸的圖片將從緩存中取出,重新調整大小,然后緩存。

Glide 的這種方式優點是加載顯示非常快。而 Picasso 的方式則因為需要在顯示之前重新調整大小而導致一些延遲。

磁盤緩存

磁盤緩存位置和緩存大小
一般的圖片緩存指的就是磁盤緩存,把網絡上的圖片緩存到本地,這樣就不需要每次都從網絡加載,既提高了加載速度,又為用戶節省了流量。

Glide在默認情況下是開啟磁盤緩存的,而且提供了豐富的API來讓開發者自己配置和管理磁盤緩存。

開發者可以通過構建一個自定義的GlideModule來配置Glide磁盤緩存的位置和大小。最簡單的方法如下:

public class DiskCacheMoudle implements GlideModule {
    @Override
    public void applyOptions(Context context, GlideBuilder builder) {
        builder.setDiskCache(new InternalCacheDiskCacheFactory(context, "glide_cache", 100 * 1024 * 1024));
        //builder.setDiskCache(new ExternalCacheDiskCacheFactory(context, "glide_cache", 100 * 1024 * 1024));
    }
    @Override
    public void registerComponents(Context context, Glide glide) {
    }
}

其中第二個參數為緩存的目錄名稱,第三個參數為緩存大小,單位是Byte。
InternalCache構建的緩存是在應用的內部儲存,而ExternalCache則是在外部儲存。

如果不想把緩存放在上面的兩個位置怎么辦?Glide當然也支持,具體通過DiskLruCacheFactory來實現:

builder.setDiskCache(new DiskLruCacheFactory(new DiskLruCacheFactory.CacheDirectoryGetter() {
    @Override
    public File getCacheDirectory() {
        return getMyCacheLocationBlockingIO();
    }
}), 100 * 1024 * 1024);

Note: getMyCacheLocationBlockingIO 方法返回的文件不能為空,而且必須是一個已經創建好的文件目錄,不可以是文件。

磁盤緩存策略
與其他圖片加載庫的緩存機制不同,Glide緩存圖片時默認只緩存最終加載的那張圖片。

舉個栗子,你要加載的圖片分辨率為1000x1000,但是最終顯示該圖片的ImageView大小只有500x500,那么Glide就會只緩存500x500的小圖。

這也是在從磁盤緩存中加載圖片時Glide比Picasso快的原因。

不過,你可以改變這種行為,讓Glide既緩存全尺寸又緩存其他尺寸:

Glide.diskCacheStrategy(DiskCacheStrategy.ALL)

Glide目前提供了四種緩存策略:

  • DiskCacheStrategy.NONE 不緩存文件
  • DiskCacheStrategy.SOURCE 只緩存原圖
  • DiskCacheStrategy.RESULT 只緩存最終加載的圖(默認的緩存策略)
  • DiskCacheStrategy.ALL 同時緩存原圖和結果圖

磁盤緩存算法
在Glide中磁盤緩存默認使用的是LRU(Least Recently Used)算法。如果你想使用其他的緩存算法,就只能通過實現DiskCache接口來完成了。

內存緩存

使用內存緩存可以獲得更快的圖片加載速度,因為減少了耗時的IO操作。

眾所周知,Bitmap是Android中的內存大戶,頻繁的創建和回收Bitmap必然會引起內存抖動。

Glide中有一個叫做BitmapPool的類,可以復用其中的Bitmap對象,從而避免Bitmap對象的創建,減小內存開銷。

當配置內存緩存時,我們也應該同時配置BitmapPool的大小。具體方法也是通過自定義的GlideModule來實現的:

builder.setMemoryCache(new LruResourceCache(yourSizeInBytes));
builder.setBitmapPool(new LruBitmapPool(sizeInBytes));

一般情況下,開發者是不需要自己去指定它們的大小的,因為Glide已經幫我們做好了。
默認的內存緩存和BitmapPool的大小由MemorySizeCalculator根據當前設備的屏幕大小和可用內存計算得到。
此外Glide還支持動態的緩存大小調整,在存在大量圖片的Activity/Fragment中,開發者可以通過setMemoryCategory方法來提高Glide的內存緩存大小,從而加快圖片的加載速度。

Glide.get(context)
   .setMemoryCategory(MemoryCategory.HIGH);

MemoryCategory有3個值可供選擇:

  • MemoryCategory.HIGH(初始緩存大小的1.5倍)
  • MemoryCategory.NORMAL(初始緩存大小的1倍)
  • MemoryCategory.LOW(初始緩存大小的0.5倍)

在有些情況下我們不希望做內存緩存(比如加載GIF圖片),這個時候可以調用skipMemoryCache(true)方法跳過內存緩存。

緩存動態 URL 的圖片

一般情況下我們從網絡上獲取到的圖片Url都是靜態的,即一張圖片對應一個Url。那么如果是一張圖片對應多個Url呢?緩存不就沒有意義了。因為圖片加載庫都是拿圖片的Url來作為緩存的key的,Glide也不例外,只是會更加復雜一些。如果你開啟了Glide的log,就會在控制台看到Glide是如何指定緩存key的。關於如何打開log,請參考這篇文章。一般來說,Glide的key由圖片的url、view的寬和高、屏幕的尺寸大小和signature組成。

在什么情況下才會出現動態的Url呢?一個很典型的例子就是因為圖片的安全問題在原來圖片的Url后面加上訪問憑證。訪問憑證與時間關聯,這樣一來,在不同時間同一圖片的Url就會不同,緩存就會失效。以七牛的私有空間為例,我們來看看如何去緩存這類圖片。從七牛關於私有空間的文檔中可以得到:最終的Url = 原Url + ?e=過期時間 + token=下載憑證。那么就只需要在Glide緩存時將Url中“?”后面的字符串截去就可以了。

首先新建一個叫做QiNiuImage的類:

public class QiNiuImage {
    private final String imageUrl;
    public QiNiuImage(String imageUrl) {
        this.imageUrl = imageUrl;
    }
    public String getImageUrl() {
        return imageUrl;
    }
    public String getImageId() {
        if (imageUrl.contains("?")) {
            return imageUrl.substring(0, imageUrl.lastIndexOf("?"));
        } else {
            return imageUrl;
        }
    }
}

其中getImageUrl方法返回真實的Url,getImageId方法返回未添加下載憑證前的Url。

然后再自定義一個實現ModelLoader接口的QiNiuImageLoader:

public class QiNiuImageLoader implements StreamModelLoader<QiNiuImage> {
    @Override
    public DataFetcher<InputStream> getResourceFetcher(final QiNiuImage model, int width, int height) {
        return new HttpUrlFetcher(new GlideUrl(model.getImageUrl())) {
            @Override
            public String getId() {
                return model.getImageId();
            }
        };
    }
    public static class Factory implements ModelLoaderFactory<QiNiuImage, InputStream> {
        @Override
        public ModelLoader<QiNiuImage, InputStream> build(Context context, GenericLoaderFactory factories) {
            return new QiNiuImageLoader();
        }
        @Override
        public void teardown() { /* no op */ }
    }
}

其中HttpUrlFetcher的getId方法就是組成緩存的key的重要部分。這也是我們的核心原理。

將這個ModelLoader注冊到GlideModule中,並在AndroidManifest.xml中注冊:

public class QiNiuModule implements GlideModule {
    @Override
    public void applyOptions(Context context, GlideBuilder builder) {
    }
    @Override
    public void registerComponents(Context context, Glide glide) {
        glide.register(QiNiuImage.class, InputStream.class, new QiNiuImageLoader.Factory());
    }
}
<meta-data
        android:name="com.yourpackagename.QiNiuModule"
        android:value="GlideModule"/>

最后只需要在加載此類圖片時,使用下面這段代碼就可以了。即使圖片的token更換了也不會重新從網絡上下載而是直接讀取本地緩存。

Glide.with(context)
      .load(new QiNiuImage(imageUrl)
      .into(imageView);

圖片質量

如果將一張 1920x1080 像素的圖片加載到 768x432 的 ImageView 中,會感覺 Glide 加載的圖片質量要稍差於 Picasso,Glide 加載的圖片沒有 Picasso 那么平滑,這是因為 Glide 默認的 Bitmap 格式是 RGB_565,比 ARGB_8888 格式的內存開銷要小一半。

如果你通過創建一個新的 GlideModule 將 Bitmap 格式轉換到 ARGB_8888,會發現 Picasso 的內存開銷仍然遠大於 Glide。原因在於 Picasso 是加載了全尺寸的圖片到內存,然后讓 GPU 來實時重繪大小。而 Glide 加載的大小和 ImageView 的大小是一致的,因此更小。

當然,Picasso 也可以指定加載的圖片大小的:

Picasso.with(this)
    .load("http://nuuneoi.com/uploads/source/playstore/cover.jpg")
    .resize(768, 432)
    .into(ivImgPicasso);

但是問題在於你需要主動計算 ImageView 的大小,或者說你的 ImageView 大小是具體的值(而不是wrap_content),你也可以這樣:

Picasso.with(this)
    .load("http://nuuneoi.com/uploads/source/playstore/cover.jpg")
    .fit()
    .centerCrop()
    .into(ivImgPicasso);

現在Picasso的內存開銷就和Glide差不多了。

雖然內存開銷差距不大,但是在這個問題上 Glide 完勝 Picasso。因為 Glide 可以自動計算出任意情況下的 ImageView 大小。

使用 GlideModule 定制 Glide

官方文檔

如果你對 Glide 默認的配置不滿意,你可以創建一個新的 GlideModule 對 Glide 默認配置進行修改,比如上面說的將 Bitmap 格式轉換到 ARGB_8888

public class GlideConfiguration implements GlideModule {
    @Override
    public void applyOptions(Context context, GlideBuilder builder) {
        // Apply options to the builder here.
        builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888);
    }

    @Override
    public void registerComponents(Context context, Glide glide) {
        // register ModelLoaders here.
    }
}

GlideModule 用來在 Glide 單例創建之前應用所有的選項配置,該方法每次實現只會被調用一次。

GlideModule接口的第二個方法registerComponents(Context context, Glide glide)用來在Glide單例創建之后但請求發起之前注冊組件,該方法每次實現只會被調用一次。通常在該方法中注冊 ModelLoader。
GlideModule接口的第一個方法applyOptions(Context context, GlideBuilder builder)給你了一個 GlideBuilder 對象作為變量,這個 GlideBuilder 對象給你訪問了 Glide 重要的核心組件,我們可以調用的方法有:

1、setBitmapPool(BitmapPool bitmapPool) Bitmap池

builder.setBitmapPool(new LruBitmapPool(sizeInBytes));

Bitmap 池用來允許不同尺寸的 Bitmap 被重用,這可以顯著地減少因為圖片解碼像素數組分配內存而引發的垃圾回收。默認情況下 Glide 使用 LruBitmapPool 作為 Bitmap 池,LruBitmapPool 采用LRU算法保存最近使用的尺寸的 Bitmap。我們可以通過它的構造器設置最大緩存內存大小。

2、setMemoryCache(MemoryCache memoryCache) 內存緩存

builder.setMemoryCache(new LruResourceCache(yourSizeInBytes));

MemoryCache 用來把 resources 緩存在內存里,以便能馬上能拿出來顯示。默認情況下 Glide 使用 LruResourceCache,我們可以通過它的構造器設置最大緩存內存大小。

MemoryCacheBitmapPool 的默認大小由 MemorySizeCalculator 類決定,MemorySizeCalculator 會根據給定屏幕大小可用內存算出合適的緩存大小,這也是推薦的緩存大小,我們可以根據這個推薦大小做出調整。

3、setDiskCache(DiskCache.Factory diskCacheFactory) 磁盤緩存
設置一個用來創建 DiskCache 的工廠。默認情況下 Glide 使用 InternalCacheDiskCacheFactory 內部工廠類創建DiskCache,緩存目錄為程序內部緩存目錄/data/data/your_package_name/image_manager_disk_cache/(不能被其它應用訪問)且緩存最大為250MB

當然,可以通過 InternalCacheDiskCacheFactory 構造器更改緩存的目錄和最大緩存大小,如:

builder.setDiskCache(new InternalCacheDiskCacheFactory(context,cacheDirectoryName, yourSizeInBytes));

還可以指定緩存到外部磁盤SD卡上:

builder.setDiskCache(new ExternalCacheDiskCacheFactory(context,cacheDirectoryName, yourSizeInBytes));

4、setResizeService(ExecutorService service) 和 setDiskCacheService(ExecutorService service)
設置一個用來檢索 cache 中沒有的 Resource 的 ExecutorService 實現。為了使縮略圖請求正確工作,實現類必須把請求根據 Priority 優先級排好序。

5、setDecodeFormat(DecodeFormat decodeFormat) 圖片質量
為所有的默認解碼器設置解碼格式。如 DecodeFormat.PREFER_ARGB_8888。默認是DecodeFormat.PREFER_RGB_565,因為相對於ARGB_88884字節/像素可以節省一半的內存,但不支持透明度且某些圖片會出現條帶。

設置完以后,下一步我們需要全局的去聲明這個類,讓 Glide 知道它應該在哪里被加載和使用。Glide 會掃描 AndroidManifest.xmlGlideModulemeta-data 聲明,因此,你必須在 AndroidManifest.xml<application> 標簽內去聲明這個剛剛創建的 GlideModule。

<meta-data android:name="***.GlideConfiguration"
           android:value="GlideModule"/>

請確保你將 android:name 屬性改成你的包名+類名的形式。如果你想刪掉 GlideModule,只需要把它從 AndroidManifest.xml 中移除就可以了,Java 類可以保存,說不定以后會用呢。如果它沒有在 AndroidManifest.xml 中被引用,那它不會被加載或被使用。你可以同時聲明多個 GlideModule。Glide 將會(沒有特定順序)得到所有的聲明 module。

比 Picasso 強大的地方

  • Glide 可以加載 GIF 動態圖,而 Picasso 不能。同時因為 Glide 和 Activity/Fragment 的生命周期是一致的,因此 gif 的動畫也會自動的隨着 Activity/Fragment 的狀態暫停、重放。Glide 的緩存在 gif 這里也是一樣,調整大小然后緩存。
  • Glide 可以將任何的本地視頻解碼成一張靜態圖片。
  • 可以配置圖片顯示的動畫,而 Picasso 只有一種動畫:fading in。
  • 可以使用 thumbnail() 產生一個你所加載圖片的 thumbnail。

其實還有一些特性,不過不是非常重要,比如將圖像轉換成字節數組等。

小結

本人四個庫都使用了一遍,對比后發現Fresco確實強大,加載大圖 Fresco 最強,有的圖 Glide 和 Picasso 加載不出來,換上 Fresco 妥妥的,不過 Fresco 比較龐大,推薦在主要都是圖片的 app 中使用,一般的 app 使用 Glide 或 Picasso 就夠了!

Glide 和 Picasso 都是非常完美的庫,Glide 加載圖像以及磁盤緩存的方式都要優於 Picasso,速度更快,並且 Glide 更有利於減少 OutOfMemoryError 的發生。,GIF 動畫是 Glide 的殺手鐧,不過 Picasso 的圖片質量更高。

建議使用 Glide,如有需要,可以 將Bitmap 格式換成 ARGB_8888、讓 Glide 緩存同時緩存全尺寸和改變尺寸兩種。

Picasso 16K

Picasso是Square公司開源的一個Android平台上的圖片加載框架,簡單易用,一句話搞定項目中的圖片加載,好用到令人發指。相比而言,這個也算是一個出來時間比較長的框架了。

使用示例:

Picasso.with(this)
    .load("url")
    .placeholder(R.mipmap.ic_default)
    .into(imageView);

添加依賴

compile 'com.squareup.picasso:picasso:2.5.2'

A powerful image downloading and caching library for Android

總結

  • 優點:圖片質量高
  • 缺點:加載速度一般
  • 特點:只緩存一個全尺寸的圖片,根據需求的大小在壓縮轉換

Fresco 15K

FaceBook出品,支持Android 2.3 (Gingerbread)及以上

尼瑪,他竟然有專門的 中文文檔

Fresco 是 Facebook 出品的新一代的圖片加載庫,我們知道 Android 應用程序可用的內存有限,經常會因為圖片加載導致 OOM,雖然我們有各種手段去優化,盡量減少出現 OOM 的可能性,但是永遠沒法避免,尤其某些低端手機 OOM 更是嚴重。而 Facebook 就另辟蹊徑,既然沒法在 Java 層處理,我們就在更底層的 Native 堆做手腳。於是 Fresco 將圖片放到一個特別的內存區域叫 Ashmem 區,就是屬於 Native 堆,圖片將不再占用 App 的內存,Java 層對此無能為力,這里是屬於 C++ 的地盤,所以能大大的減少 OOM。

添加依賴

compile 'com.facebook.fresco:fresco:1.2.0'

//**************下面的依賴需要根據需求添加******************//
// 在 API < 14 上的機器支持 WebP 時,需要添加
compile 'com.facebook.fresco:animated-base-support:1.2.0'

// 支持 GIF 動圖,需要添加
compile 'com.facebook.fresco:animated-gif:1.2.0'

// 支持 WebP (靜態圖+動圖),需要添加
compile 'com.facebook.fresco:animated-webp:1.2.0'
compile 'com.facebook.fresco:webpsupport:1.2.0'

// 僅支持 WebP 靜態圖,需要添加
compile 'com.facebook.fresco:webpsupport:1.2.0'

GitHub上的介紹:

Fresco is a powerful system for displaying images in Android applications.

Fresco takes care of image loading and display, so you don't have to. It will load images from the network, local storage, or local resources, and display a placeholder占位符 until the image has arrived. It has two levels of cache; one in memory and another in internal storage.

In Android 4.x and lower, Fresco puts images in a special region of Android memory. This lets your application run faster - and suffer the dreaded OutOfMemoryError much less often.

Fresco also supports:

  • streaming of progressive JPEGs
  • display of animated GIFs and WebPs
  • extensive廣闊的 customization of image loading and display
  • and much more!

Fresco 支持許多URI格式,但 Fresco 不支持 相對路徑的URI。所有的 URI 都必須是絕對路徑,並且帶上該 URI 的 scheme。如下:

類型 SCHEME 示例
遠程圖片 http:// HttpURLConnection或者參考使用其他網絡加載方案
本地文件 file:// FileInputStream
ContentProvider content:// ContentResolver
asset目錄下的資源 asset:// AssetManager
res目錄下的資源 res:// Resources.openRawResource
Uri中指定圖片數據 data:mime/type;base64 數據類型必須符合rfc2397規定(僅支持UTF-8)

總結

  • 優點:支持圖像漸進式呈現,大公司出品,后期維護有保障
  • 缺點:框架體積較大,3M左右會增大apk的大小;操作方式不是特別簡單,有一定學習成本
  • 特點:有兩級內存一級文件的緩存機制,並且有自己特別的內存區域來處理緩存,避免oom

Universal-Image-Loader 16K

jar包下載

UIL可以算是老牌最火的圖片加載庫了,使用過這個框架的項目可以說多到教你做人,我第一次把第三方開源圖片加載框架加入項目中的就是這個了,當時感覺瞬間逼格上漲,媽媽再也不用擔心出現OOM和ListView圖片錯亂了。

Powerful and flexible library for loading, caching and displaying images on Android.

尼瑪,雖然這哥們很久基本都不更新了,而且還不提供Gradle的支持,但目前依然是星星最多的一個圖片處理庫

加載策略

  • 每一個圖片的加載和顯示任務都運行在獨立的線程中,除非這個圖片緩存在【內存】中,這種情況下圖片會立即顯示。
  • 如果需要的圖片緩存在【本地】,他們會開啟一個獨立的線程隊列。
  • 如果在緩存中沒有正確的圖片,任務線程會從線程池中獲取,因此,快速顯示緩存圖片時不會有明顯的障礙。

控制OOM

  • 減少線程池中線程的個數,在ImageLoaderConfiguration中的.threadPoolSize中配置,推薦配置1-5
  • 在DisplayImageOptions選項中配置bitmapConfig為Bitmap.Config.RGB_565,因為默認是ARGB_8888, 使用RGB_565會比使用ARGB_8888少消耗2倍的內存
  • 在ImageLoaderConfiguration中配置圖片的內存緩存為memoryCache(new WeakMemoryCache()) 或者不使用內存緩存
  • 在DisplayImageOptions選項中設置.imageScaleType(ImageScaleType.IN_SAMPLE_INT)或者imageScaleType(ImageScaleType.EXACTLY)

我們在使用該框架的時候盡量的使用displayImage()方法去加載圖片,loadImage()是將圖片對象回調到ImageLoadingListener接口的onLoadingComplete()方法中,需要我們手動去設置到ImageView上面,displayImage()方法中,對ImageView對象使用的是WeakReferences,方便垃圾回收器回收ImageView對象,如果我們要加載固定大小的圖片的時候,使用loadImage()方法需要傳遞一個ImageSize對象,而displayImage()方法會根據ImageView對象的測量值,或者android:layout_widthandroid:layout_height設定的值,或者android:maxWidth 和/或 android:maxHeight設定的值來裁剪圖片。

總結

  • 優點:豐富的配置選項
  • 缺點:有不維護的趨勢,可能被當前圖片框架替代
  • 特點:三級緩存的策略

2018-12-20

附件列表

     


    免責聲明!

    本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



     
    粵ICP備18138465號   © 2018-2025 CODEPRJ.COM