Glide入門教程——10. 回調:定制view中使用SimpleTarget和ViewTarget

Glide — 回調:定制view中使用SimpleTarget和ViewTarget

原文:Callbacks: SimpleTarget and ViewTarget for Custom View Classes
作者:Norman Peitek
翻譯:Dexter0218

前面3篇都是圍繞著優化Glide的流程和提升用戶體驗。下面的幾篇會如何使用Glide中的的回調技術。目前為止,我們總是假設加載圖片或Gif到ImageView上,但那并不適用所有的情況。本文將要介紹在沒有指定的ImageView時,著手獲取一個圖片的資源。

Glide 系列概覽

  1. 入門簡介
  2. 高級加載
  3. 適配器(ListView, GridView)
  4. 占位圖& 淡入淡出動畫
  5. 圖片大小 & 縮放
  6. 播放GIF & 視頻
  7. 緩存基礎
  8. 請求優先級
  9. 縮略圖
  10. 回調:定制view中使用SimpleTarget和ViewTarget
  11. 通知欄和桌面小控件的圖片加載
  12. 異常: 調試和報錯處理
  13. 自定義變換
  14. 用animate()定制動畫
  15. 整合網絡協議棧
  16. 用Modules定制Glide
  17. Glide Module 案例: 接受自簽名HTTPS證書
  18. Glide Module 案例: 自定義緩存
  19. Glide Module 案例: 通過加載自定義大小圖片優化
  20. 動態使用 Model Loaders
  21. 如何旋轉圖片
  22. 系列綜述

Glide中的回調:Target

目前為止,我們已經能夠很方便地使用Glide去加載圖片到ImageView中。在應用場景中,Glide隱藏了大量復雜的工作。Glide在后臺線程中處理了所有的網絡請求,一旦結果準備完畢,就會調用UI線程更新ImageVIew。

在這篇文章中,我們假設我們并沒有ImageView作為圖片加載的目標。我們只需要Bitmap本身。Glide提供了一個用Target獲取Bitmap資源的方法。Target只是用來回調,它會在所有的加載和處理完畢時返回想要的結果。

Glide提供了多種多樣有各自明確目的Target。在隨后的幾個小節了逐一介紹。我們先從SimpleTarget介紹。

SimpleTarget

我們看看代碼:

private SimpleTarget target = new SimpleTarget<Bitmap>() {  
    @Override
    public void onResourceReady(Bitmap bitmap, GlideAnimation glideAnimation) {
        // do something with the bitmap
        // for demonstration purposes, let's just set it to an ImageView
        imageView1.setImageBitmap( bitmap );
    }
};

private void loadImageSimpleTarget() {  
    Glide
        .with( context ) // could be an issue!
        .load( eatFoodyImages[0] )
        .asBitmap()
        .into( target );
}

代碼的第一部分,創建一個target字段對象,里面定義了個方法,這個方法一旦Glide加載和處理完圖片將會被調用?;卣{方法傳回Bitmap作為參數,你可以在你所需要用的地方隨意使用這個Bitmap對象。

代碼的第二部分,表明了Glide里如何使用Target,明顯跟ImageView一樣!你可以傳遞一個Target或者ImageView作為參數到.into()方法里。Glide會神奇地將結果返回。這里有個不同點,我們添加了.asBitmap(),這會強制返回一個Bitmap對象。記住,Glide也可以加載Gif或視頻。為了防止在從網絡URL(可能是GIF)獲取Bitmap時,出現未知格式圖片沖突(期望是Bitmap),我們設置.asBitmap()去告訴Glide只有在資源是一個圖片是才算成功,其他的都算解析失敗。

使用Target注意事項

除了剛介紹的Target的回調系統的一個簡單版本,你要學會額外兩件事。

第一個是SimpleTarget對象的定義。java/Android可以允許你在.into()內匿名定義,但這會顯著增加在Glide處理完圖片請求前Android垃圾回收清理匿名target對象的可能性。最終,會導致圖片被加載了,但是回調永遠不會被調用。所以,請確保將你的回調定義為一個字段對象,防止被萬惡的Android垃圾回收給清理掉。

第二個關鍵部分是Glide的.with( context )。這個問題實際上是Glide一個特性問題:當你傳遞了一個context,例如當前app的activity,當activity停止后,Glide會自動停止當前的請求。這種整合到app生命周期內是非常有用的,但也是很難處理的。如果你的target是獨立于app的生命周期。這里的解決方案是使用application的context:.with( context.getApplicationContext() )。當app自己停止運行的時候,Glide會只取消掉圖片的請求。請記住,再次提醒,如果你的請求需要在activity的生命周期以外,使用下面的代碼:

private void loadImageSimpleTargetApplicationContext() {  
    Glide
        .with( context.getApplicationContext() ) // safer!
        .load( eatFoodyImages[1] 
        .asBitmap()
        .into( target2 );
}

特定大小的Target

另外一個潛在問題是Target沒有一個明確的大小。如果你傳遞一個ImageView作為.into()的參數,Glide會使用ImageView的大小來限制圖片的大小。例如如果要加載的圖片是1000x1000像素,但是ImageView的尺寸只有250x250像素,Glide會降低圖片到小尺寸,以節省處理時間和內存。顯然,由于target沒有具體大小,這對target并不起效。但是,如果你有個期望的具體大小,你可以增強回調。如果你知道圖片應當為多大,那么在你的回調定義里應當指明,以節省內存:

private SimpleTarget target2 = new SimpleTarget<Bitmap>( 250, 250 ) {  
    @Override
    public void onResourceReady(Bitmap bitmap, GlideAnimation glideAnimation) {
        imageView2.setImageBitmap( bitmap );
    }
};

private void loadImageSimpleTargetApplicationContext() {  
    Glide
        .with( context.getApplicationContext() ) // safer!
        .load( eatFoodyImages[1] )
        .asBitmap()
        .into( target2 );
}

和“普通”target唯一不同的是這個以像素為單位的圖片大小聲明:new SimpleTarget<Bitmap>( 250, 250 )。目前已經介紹了所有關于SimpleTarget的知識點。

ViewTarget

有很多原因導致我們不能直接使用ImageView。前面已經介紹了如何獲取Bitmap?,F在,我們將更深入學習。假設你有個自定義的View。由于沒有已知的方法在哪里設置圖片,Glide并不支持加載圖片到定制的View內。然而用ViewTarget會讓這個更簡單。

讓我們看一個簡單的定制View,它繼承于FrameLayout,內部使用了一個ImageView,并上面覆蓋了一個TextView:

public class FutureStudioView extends FrameLayout {  
    ImageView iv;
    TextView tv;

    public void initialize(Context context) {
        inflate( context, R.layout.custom_view_futurestudio, this );

        iv = (ImageView) findViewById( R.id.custom_view_image );
        tv = (TextView) findViewById( R.id.custom_view_text );
    }

    public FutureStudioView(Context context, AttributeSet attrs) {
        super( context, attrs );
        initialize( context );
    }

    public FutureStudioView(Context context, AttributeSet attrs, int defStyleAttr) {
        super( context, attrs, defStyleAttr );
        initialize( context );
    }

    public void setImage(Drawable drawable) {
        iv = (ImageView) findViewById( R.id.custom_view_image );

        iv.setImageDrawable( drawable );
    }
}

由于我們定制的view并不是繼承自ImageView,這里不能使用常規的.into()方法。因此,我們只能創建一個ViewTarget,用來傳遞給.into()方法:

private void loadImageViewTarget() {  
    FutureStudioView customView = (FutureStudioView) findViewById( R.id.custom_view );

    viewTarget = new ViewTarget<FutureStudioView, GlideDrawable>( customView ) {
        @Override
        public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
            this.view.setImage( resource.getCurrent() );
        }
    };

    Glide
        .with( context.getApplicationContext() ) // safer!
        .load( eatFoodyImages[2] )
        .into( viewTarget );
}

在target的回調方法中,我們在定制view上使用我們創建的setImage(Drawable drawable)方法設置圖片。同時,確保你注意到我們已經在ViewTarget的構造方法里傳遞了我們的定制view:new ViewTarget<FutureStudioView, GlideDrawable>( customView )

這應該覆蓋了所有你可能需要定制的view。你也可以在回調中做額外的工作。例如,我們可以解析即將到來的圖片的主色調,然后設置TextView的顏色。但我們相信你肯定已經有你自己的想法。

展望

在這篇較長的文章中,你已經學會了Glide中target的基礎。你已經學會了從圖片獲取Bitmap,并加載到你定制的view中??梢栽谠u論中告訴我們我們忽略了什么。

后面的文章,我們將要繼續通過例子介紹target如何向通知欄和桌面小控件加載圖片。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,182評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,489評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,290評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,776評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,510評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,866評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,860評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,036評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,585評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,331評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,536評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,058評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,754評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,154評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,469評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,273評論 3 399
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,505評論 2 379

推薦閱讀更多精彩內容

  • 一、簡介 在泰國舉行的谷歌開發者論壇上,谷歌為我們介紹了一個名叫Glide的圖片加載庫,作者是bumptech。這...
    天天大保建閱讀 7,531評論 2 28
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,733評論 25 708
  • 零、前言 本文所使用的Glide版本為3.7.0如果需要使用V4的最新版本請參考Glide V4使用指南 一、簡介...
    MrTrying閱讀 204,212評論 36 255
  • 當你看到孩子成績時,無論好壞,請想想:每個孩子都是一顆花的種子,只不過花期不同。有的花,一開始就燦爛綻放;有的花,...
    錢蓉蓉閱讀 951評論 0 1
  • 李菁《攝影夢想課堂》的攝影學習公眾號很棒。因為有許多的學員在一起學,共同進步,這樣整理出來又使大家看到優缺點,而且...
    窗花閱讀 407評論 0 0