Glide教程5-8

5. Glide-圖片縮放、調整 (Resizing & Scaling)


在上一篇博文裏,你學習瞭如何從不同的源加載圖片並且設置不同的佔位符。如果你還不會在加載的時候調整和裁剪圖片,那麼本週的博文就很重要啦!

用resize(x,y)設置圖片大小

通常來說,如果你的服務器或者API能爲你提供你需要的尺寸的圖片,那麼是最好的。因爲這需要在帶寬、內存消耗、圖片質量之前做一個平衡。
與Picasso相比,Glide在內存消耗上更高效、更智能。Glide會根據所剩的內存和ImageView的大小自動限制圖片的尺寸。Picasso也有相似的特性,但是它需要手動調用.fit(),對於Glide而言,如果某些圖片不應該被自動調整,那麼執行override(horizontalSize, verticalSize),那麼這個圖片會在顯示到ImageView之前被調整爲需要的尺寸。

Glide  
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[0])
    .override(600, 200) //按照這個像素,調整圖片的尺寸,不保持長寬比例
    .into(imageViewResize);

這對於某些情況是挺實用的:當你要加載圖片到未知尺寸的View上時;比如,如果app想要在啓動頁面加載緩存(原文:if the app wants to warm up the cache in the splash screen( warm up the cache不知道啥意思(逃),此時還不能測量ImageView的尺寸。然而,如果你已經知道圖片需要多大的尺寸,那麼使用override可以得到特定大小的圖片。

圖片裁剪

現在,因爲任何對圖片的處理、調整都會導致圖片的比例扭曲從而圖片看起來很醜。在大部分應用場景下,你都希望避免這種情況的發生。Glide提供了一些常用的變換來改變圖片的顯示。它附帶了兩個基本選項: centerCrop和fitCenter。

CenterCrop

CenterCrop() 是一種“去除多餘”的裁剪方式,它會把ImageView邊界以外的部分裁剪掉。這樣一來ImageView會被填充滿,但是這張圖片可能不會完整地顯示出來(ps:因爲超出部分都被裁剪掉了)。

Glide  
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[0])
    .override(600, 200) // resizes the image to these dimensions (in pixel)
    .centerCrop() // this cropping technique scales the image so that it fills the requested bounds and then crops the extra.
    .into(imageViewResizeCenterCrop);

FitCenter

FitCenter() 是一種“中心匹配”的方式裁剪方式,它裁剪出來的圖片長寬都會小於等於ImageView的大小,這樣一來。圖片會完整地顯示出來,但是ImageView可能並沒有被填充滿。

Glide  
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[0])
    .override(600, 200)
    .fitCenter() 
    .into(imageViewResizeFitCenter);

在後面的文章裏,我們將會提到除了CenterCrop和FitCenter以外,其他一些自定義的變換。

展望

在這篇文章裏,學習瞭如何調整圖片顯示的尺寸。這對於設計一款優秀的app是非常有用的。在我們學習Glide更多高級應用之前,我們再多講一個Glide特有的功能:顯示Gif圖片和視頻。



6. Glide-顯示Gif和視頻

在前面的文章我們講了如何從各種數據源加載並顯示圖片,我們學習瞭如何改變圖片:通過一些標準的方法設置圖片大小、裁剪。
本文將講述Glide特色功能:顯示Gif圖片和本地視頻。

顯示Gifs

有很多圖片加載框架提供了加載並顯示圖片的功能,但支持Gif則有點特殊,如果你的app需要這個功能,那麼它非常必要。Glide加載Gif的體驗讓人驚歎,因爲它非常簡單。如果你想顯示Gif,你只需要像之前那樣寫就可以了:

//這動圖嚇我一跳 - -#
String gifUrl = "http://i.kinja-img.com/gawker-media/image/upload/s--B7tUiM5l--/gf2r69yorbdesguga10i.gif";

Glide  
    .with( context )
    .load( gifUrl )
    .into( imageViewGif );

就是這麼簡單!這樣就可以在ImageView上顯示一個Gif圖片了,並且它是自動播放的。更酷的是你依然可以像之前那樣做一些額外的處理:

Glide  
    .with( context )
    .load( gifUrl )
    .placeholder( R.drawable.cupcake )//加載出來前顯示的圖片
    .error( R.drawable.full_cake )//加載失敗後顯示的圖片
    .into( imageViewGif );

Gif Check :確保是Gif圖片

以上代碼潛在的問題是:如果你的圖片源存放的不是一張Gif,那麼可能只是一張普通的圖片,沒有辦法聲明這種情況。Glide允許Gifs或者是普通圖片作爲load()方法的參數,如果開發者認爲URL是一張Gif,而實際上不是的話。Glide沒有辦法自動檢測到。因此,這裏提供了另一種方法,來確保Glide請求到的是一張Gif動圖 asGif():

Glide  
    .with( context )
    .load( gifUrl )
    .asGif()
    .error( R.drawable.full_cake )//加載失敗 的圖片
    .into( imageViewGif );

如果gifUrl指向一張Gif圖片,那麼萬事大吉。但如果不是,那麼與之前不同的是,此時Glide會認爲是加載失敗。那麼就有一個好處,.error()方法會被回調過來,那麼就會顯示我們指定的 加載失敗 的圖片。就算gifUrl指向一張完美的圖片(啥圖?),只要它不是Gif動圖,還是會被認爲是加載失敗。

Cache Settings :緩存設置

在大多數情況下,如果你調用了.diskCacheStrategy(DiskCacheStrategy.SOURCE),那麼加載Gif的時候明顯會更快:

Glide  
    .with( context )
    .load( gifUrl )
    .asGif()
    .error( R.drawable.full_cake )
    .diskCacheStrategy(DiskCacheStrategy.SOURCE)
    .into( imageViewGif );
作者:我們將在12月份出一個新的教程:講述關於 Glide緩存 的更多的細節和背後實現;

Display Gif as Bitmap:將Gif轉爲Bitmap顯示

如果你的app通過一個包含許多圖片鏈接的列表(List<url>)來顯示圖片,那麼可能會包含普通圖片和Gif動圖。有時候你可能想不要完整地播放整個Gif圖片,如果你只想要顯示Gif的第一幀畫面,那麼asBitmap()就可以保證作爲一張普通的圖片來顯示,即使鏈接指向的是一張Gif動圖。

Glide  
    .with( context )
    .load( gifUrl )
    .asBitmap()
    .into( imageViewGifAsBitmap );

以上,就是所有Glide顯示Gifs圖片的知識,非常簡單,試試吧!

Display of Local Videos:播放本地視頻

Gif的加強版就是視頻啦,Glide同樣可以顯示視頻文件的縮略圖,並且是和視頻同樣長度的。假設我們通過讓用戶選擇來獲取一個視頻文件的路徑:

String filePath = "/storage/emulated/0/Pictures/example_video.mp4";

Glide  
    .with( context )
    .load( Uri.fromFile( new File( filePath ) ) )
    .into( imageViewGifAsBitmap );

再次提醒:這隻對本地視頻文件有效!其他不是存儲在設備上的視頻(比如網絡視頻)是不能播放的。另外,它只會顯示視頻的第一幀畫面。
如果你想播放視頻或者從網絡鏈接上查看視頻,那麼試試這個 VideoView.(這個需要f牆,貼一篇簡書的

Outlook:展望

讀完這篇文章,你應該可以像加載普通圖片一樣去加載Gif和本地視頻文件了。Glide使得顯示Gif圖片非常流暢、方便;下一週,我們將介紹Glide的緩存機制。



6. Glide-緩存基礎(caching-basics)

在瞭解完圖片的加載、顯示、處理之後,接下來繼續研究優化。成功、高效加載圖片的基本特性之一就是利用緩存。在本文,我們將會了解Glide的緩存機制的基礎部分。

Cache Basics:緩存基礎

在設計一款Android應用的時候,一個好用的圖片加載框架應該嘗試最小化網路請求的次數。Glide也一樣,Glide默認通過內存和磁盤緩存來避免不必要的網絡請求。在後續的文章中我們會具體看看其實現細節。如果你已經迫不及待,隨時可以查看這個官方文檔
對於現在,重要的是,所有的圖片請求都會在內存和磁盤上建立緩存。緩存通常都是非常有用的,然而在某些情況下又不希望它這麼做。在下一節,我們將學習如何在一次請求中改變Glide的緩存策略。

Using Cache Strategies:使用緩存策略

如果你使用過Glide,你注意到根本不需要爲開啓緩存做額外的事,它自然而然就實現了。然而,如果你知道某張圖片改變非常快,那麼你應該要避免某些緩存。

Glide提供了一些方法來調整內存和磁盤緩存策略,讓我們先來看看內存緩存。

Memory Cache:內存緩存

我們假設一種非常簡單的情形:從網絡上加載一張圖片到ImageView上:

Glide
    .with(context)
    .load(eatFoodyImage[0])
    .skipMemoryCache( true )
    .into(imageViewInternet);

你已經注意到我們這裏使用.skipMemoryCache( true )來特地告訴Glide,讓它跳過內存緩存。這意味着Glide不會將它放入到內存緩存當中。需要注意的是,這只是影響了內存緩存,Glide依然會使用磁盤緩存來避免額外的網絡請求。

很容易理解的是,Glide是默認將所有的圖片資源都加入到內存緩存中的。因此,沒有必要專門去調用.skipMemoryCache( false )這個方法。

提示:要注意的是,對於同一個圖片鏈接,如果你初次請求的時候沒有調用.skipMemoryCache( true ),後面又調用了這個方法,那麼它會被加入到內存緩存當中。當你想調整緩存策略的時候,確保你在請求同一個圖片的時候保持策略統一。

Skipping Disk Cache:不使用磁盤緩存

基於你已經學習完上面的章節,你知道即使讓內存緩存失效,圖片請求依然會將圖片存儲在設備的磁盤上。如果你有一張圖片,它指向同一個鏈接上,但是它改變得很快,那麼你可能也不想讓它存儲在磁盤上。

你可以通過.diskCacheStrategy()方法改變Glide的磁盤緩存策略。與.skipMemoryCache()不同的是,它需要傳入不同的枚舉值,而不僅僅是布爾值。如果你想讓磁盤緩存失效,將DiskCacheStrategy.NONE作爲參入傳入即可:

Glide  
    .with( context )
    .load( eatFoodyImages[0] )
    .diskCacheStrategy( DiskCacheStrategy.NONE )
    .into( imageViewInternet );

這樣的話,這張圖片的一點磁盤緩存都不會有。然而,它默認會使用內存緩存。爲了讓兩個緩存都失效,把它倆組合一下就好:

Glide  
    .with( context )
    .load( eatFoodyImages[0] )
    .diskCacheStrategy( DiskCacheStrategy.NONE )//它
    .skipMemoryCache( true )//還有它
    .into( imageViewInternet );

Customize Disk Cache Behavior:自定義磁盤緩存策略

我們前面已經提到了,對於磁盤緩存,Glide不止一個選項。在知道有哪些選項之前,你要明白磁盤緩存是相當複雜的東西。例如,Picasso只是緩存完整圖片。然而,Glide的緩存不僅緩存原圖、完整的圖片還有額外一些縮小的圖片。
例如,如果你請求一張圖片是1000 x 1000像素,然後你的ImageView是500 x 500像素,那麼Glide會將這兩個尺寸圖片都緩存起來。
現在你應該明白磁盤緩存策略diskCacheStrategy()中,不同的枚舉參數之間的區別了:

  • DiskCacheStrategy.NONE 就像上面討論的,啥都不緩存
  • DiskCacheStrategy.SOURCE 只緩存原圖,在我們上面的例子中就是 1000 x 1000像素的那張
  • DiskCacheStrategy.RESULT 經過裁剪、調整後,只緩存最終的圖片(這是默認選項
  • DiskCacheStrategy.ALL 緩存所有版本的圖片

作爲最後一個例子,如果你有一張圖片,你知道會經常修改它並且會有各種不同的版本,那麼把它指定爲僅緩存原圖是很有意義的。因此,我們可以使用DiskCacheStrategy.SOURCE來告訴Glide僅緩存原圖即可:

Glide  
    .with( context )
    .load( eatFoodyImages[2] )
    .diskCacheStrategy( DiskCacheStrategy.SOURCE )
    .into( imageViewFile );

Invalidate Cache for Single Image:不緩存某張圖片

由於Glide對於同一張圖片可以採取不一樣的的緩存方式,想要簡單的清除某張圖片的緩存不是一件容易的事。你需要找到這張圖片所有的變體,然後針對性地讓那個緩存失效。
這是一個相當繁瑣的步驟,官方文檔裏講解得非常清楚。

展望

在本文,你學習了Glide緩存圖片的基礎知識,並且知道如何調整緩存策略。基於你的需求,在後續的博文裏,我們將回到這個話題講解更多高級的優化。然而,這篇文章已經提供了非常有效的方法讓你可以好好地利用Glide的緩存了。

下週,我們將看看 良好的用戶體驗的另一個關鍵點:優先圖片請求!



7. Glide-圖片請求優先級(request-priorities)

上一週,我們講了圖片加載的一個關鍵:緩存! 如果你還沒有看過,那麼值得翻回去看看。本週,我們將瞭解Glide的另一個重要特性:按照優先級依次請求圖片。

Prioritizing Image Requests:設置圖片請求優先級

你經常會遇到這樣的情況,你的app需要同時加載許多圖片。我們假設有這樣一個詳情頁面:頁面上方有一張關鍵的大圖和兩張稍小一些的圖,頁面底部還有一些不那麼重要的圖片。 對於一個良好用戶體驗來說,上方的關鍵大圖應該是最先被加載並顯示的,然後再到底部那麼不那麼重要的ImageView。Glide通過.priority()方法結合Priority的枚舉值即可按照你想要的優先級來加載圖片。

但是在我們講例子如何使用這個方法之前,我們先來看看這些枚舉值,它們是作爲.priority()的參數傳入的。

Getting to know the Priority enum:優先級的枚舉值

這些枚舉總共有四種,優先級按照順序依次遞增:

  • Priority.LOW
  • Priority.NORMAL
  • Priority.HIGH
  • Priority.IMMEDIATE

immediate
adj. 立即的; 立刻的;

在我們看例子之前,你要明白這些優先級並不是非常嚴格執行的。 Glide會將它們作爲一個參考,在請求的時候儘量滿足,並不保證所有的圖片都會按照順序來請求。

但是,如果你確定某些圖片非常重要,那麼可以好好利用這個特性!

例子: Hero Element with Child Images

我們回到剛纔提到的例子:你要實現這麼一個詳情頁面:頂部有關鍵的圖片,底部有一些小圖。最佳的用戶體驗應該是:頂部的圖片最先加載出來。 因此,我們給它設置Priority.HIGH優先級。理論上,這麼做已經足夠了。但是爲了讓這例子更有趣,我們讓底部的圖片都以.priority(Priority.LOW)優先級加載:

private void loadImageWithHighPriority() {  
    Glide
        .with( context )
        .load( UsageExampleListViewAdapter.eatFoodyImages[0] )
        .priority( Priority.HIGH )
        .into( imageViewHero );
}

private void loadImagesWithLowPriority() {  
    Glide
        .with( context )
        .load( UsageExampleListViewAdapter.eatFoodyImages[1] )
        .priority( Priority.LOW )
        .into( imageViewLowPrioLeft );

    Glide
        .with( context )
        .load( UsageExampleListViewAdapter.eatFoodyImages[2] )
        .priority( Priority.LOW )
        .into( imageViewLowPrioRight );
}

如果你運行這個例子,你會發現幾乎每次都是頂部的圖先加載出來,儘管它比較大(那樣它需要更長時間來加載)。

Outlook:展望

Glide提供了非常方便的方法來設置圖片的優先級。這是一個快速、簡單提高一些用戶體驗的的方法。看看你的app和你的代碼,是否能運用到你剛學到的技巧吧!

按優先級請求通常來說非常有效,但不能解決所有的問題。假設你要下載一張非常大的圖片,如論你設置了什麼優先級,下載和處理都要花費一定的時間。
下一週,爲了更好地提升用戶體驗,我們將介紹另一個Glide外的工具:thumbnails!



8. Glide-縮略圖(thumbnails)

上週,我們學習了一些在加載和顯示圖片的時候提高用戶體驗的方法。通過 緩存設置請求優先級 已經爲流暢的體驗提供了關鍵的一步了。然而,如果你加載的圖片非常大,那麼會花費較長的一段時間直到它顯示出來。在本博文中,我們將探索另一個優化的途徑:thumbnails(縮略圖,下文不譯)

Thumbnails的優勢

在你使用Thumbnails來優化之前,先確保你已經理解並充分利用了 緩存優先請求。如果所有的努力都已經做了,那麼試試Thumbnails是否能提升你的Android應用。

Thumbnails跟我們之前講的佔位符還不太一樣,佔位符在app裏面是指定好的某些資源文件。Thumbnails的話則是一個動態的佔位符,它也可以從網絡上加載得來。
Thumbnails會在實際的請求和處理之前顯示出來,不管什麼原因,如果Thumbnails在原圖加載後纔出現,它會自動消失而不會替換原圖。

提示:爲了更加時更加流暢,另一個非常好的方式是用一種顏色來替換佔位符的背景色,這個顏色是從目標圖裏提取出來的,可以看看我們寫的一個文檔

ps:以下是我從作者提到的文檔裏面摳出來的圖,來感受一下:

Simple Thumbnails:簡單縮略圖

Glide提供了兩種不同的縮略圖。第一種比較簡單,就是在加載原圖的時候顯示一張更小尺寸的圖片。這種方式尤其適用於ListView和詳情頁面的組合當中。 如果你早已經在ListView中加載了圖片,就像我們剛纔假設的,250x250像素的圖片,在進入其詳情頁面的時候,需要一張更大尺寸的圖。然而,對於用戶而言。他們早早就已經看到一張圖片(小圖)了,爲什麼還會出現先顯示佔位符,過了幾秒後顯示大圖的情況?

對於這種情況,我們更應該在詳情頁面繼續顯示那張250x250的圖片,然後在後臺加載所需要的大圖。Glide使用.thumbnail()就可以做到,這是傳入的參數是一個浮點數,它代表尺寸的倍數。

Glide  
    .with( context )
    .load( UsageExampleGifAndVideos.gifUrl )
    .thumbnail( 0.1f )
    .into( imageView2 );

例如,你傳了0.1f作爲參數,那麼Glide則會顯示原圖大小的10%。如果原圖的尺寸是1000x1000像素,那麼縮略圖就是100x100像素。由於縮略圖會比ImageView要小許多,所以你要確保一個準確的縮放比例。

說明一下,所有圖片請求的設置同樣適用於縮略圖。例如,你請求某張圖片時做了一個灰度變換,那麼對於它的縮略圖也是同樣會生效的。

Advanced Thumbnails with Complete Different Requests 高級縮略圖,通過完成不一樣的請求

雖然使用.thumbnail()傳入一個浮點數非常簡單高效,但不是所有情況都使用。如果縮略圖也需要從網絡加載各種尺寸,那麼它可能也快不了多少。因此,Glide提供了另一種加載縮略圖的方法。

第二種方式就是傳入一個新的圖片請求作爲參數,我們來看看例子:

private void loadImageThumbnailRequest() {  
    // setup Glide request without the into() method
    DrawableRequestBuilder<String> thumbnailRequest = Glide
        .with( context )
        .load( eatFoodyImages[2] );

    // pass the request as a parameter to the thumbnail request
    Glide
        .with( context )
        .load( UsageExampleGifAndVideos.gifUrl )
        .thumbnail( thumbnailRequest )
        .into( imageView3 );
}

區別在於第一個圖片請求與第二個圖片請求是完全獨立的,縮略圖可以是其他不同的資源id或者圖片鏈接,你可以對它做一些變換等等。

提示:如果你想更帶勁一點,你可以遞歸地調用一些請求作爲圖片的縮略圖請求參數

Outlook: 展望

本文介紹了Glide兩種加載縮略圖的方式,不要忘記在你的優雅的app上使用哦!它能極大地減少空白的ImageView出現在你的app上。如果你有什麼疑問,請通過評論讓我們知道!

下週,我們將學習如何在不是ImageView的控件上顯示圖片,敬請關注!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章