Glide 知識梳理(2) - 自定義Target

一、概述

首先,我們回顧一下Glide的基本用法,我們的最后一步都是調(diào)用into(ImageView imageView),通過斷點,我們可以看到正是這一步觸發(fā)了圖片的請求:


這個ImageView最終會通過buildTarget方法,封裝在GlideDrawableImageViewTarget當(dāng)中,然后調(diào)用GenericRequestBuilder#into方法發(fā)起請求,Glide一直跟蹤這個Target,并在獲得圖片資源之后,通知Target來更新它內(nèi)部持有的ImageView的引用。
這個過程就好像是我們平時請求網(wǎng)絡(luò)時,會傳入一個Callback,等到異步的操作執(zhí)行完畢后,通過Callback傳回請求的資源來更新UI。
通過源碼,可以看到和Target相關(guān)的類有:

  • Target
  • BaseTarget
    • SimpleTargetAppWidgetTarget、PreloadTatget、NotificationTarget
    • ViewTarget
      • ImageViewTargetGlideDrawableImageViewTargetBitmapImageViewTarget、DrawableImageViewTarget

今天這篇文章,我們就來學(xué)習(xí)一下SimpleTargetViewTarget的用法,主要參考了下面鏈接中的文章:

https://futurestud.io/tutorials/glide-callbacks-simpletarget-and-viewtarget-for-custom-view-classes

二、SimpleTarget

SimpleTarget可以看作是請求的回調(diào),我們在回調(diào)當(dāng)中進行處理,而不是傳入ImageViewGlide去負責(zé)更新。

2.1 基本用法

先看一下SimpleTarget的用法:

    public void loadSimpleTarget(View view) {
        MySimpleTarget mySimpleTarget = new MySimpleTarget();
        Glide.with(this)
                .load(R.drawable.book_url)
                .into(mySimpleTarget);
    }

    private class MySimpleTarget extends SimpleTarget<GlideDrawable> {
        
        @Override
        public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
            mImageView.setImageDrawable(resource.getCurrent());
        }
    }

我們首先定義了一個SimpleTarget,然后把它通過into方法傳入。這樣當(dāng)Glide去服務(wù)器請求圖片成功之后,它會把請求到的圖片資源作為GlideDrawable傳遞回來,你可以使用這個GlideDrawable.getCurrent()進行自己想要的操作。
關(guān)于上面SimpleTarget的使用需要知道兩點:

  • 由于我們把SimpleTarget定義成了局部變量,那么它很有可能會被回收,一旦它被回收,那么我們收不到任何的回調(diào)了。
  • 我們在with中傳入了ActivityContext,那么Glide就會監(jiān)聽Activity生命周期的變化,當(dāng)Activity退到后臺之后,停止該請求。如果你希望它獨立于Activity的生命周期,那么需要傳入一個ApplicationContext。

2.2 設(shè)置資源的大小

當(dāng)我們傳入ImageView時,Glide會根據(jù)ImageView的大小來自動調(diào)整緩存的圖片資源大小,而當(dāng)我們使用Target的時候,并沒有提供這個條件來給Glide,因此,為了縮短處理時間和減少內(nèi)存,我們可以按下面的方法來指定緩存的大?。?/p>

    public void loadSimpleTarget(View view) {
        MySimpleTarget mySimpleTarget = new MySimpleTarget(50, 50);
        Glide.with(this)
                .load(R.drawable.book_url)
                .into(mySimpleTarget);
    }

    private class MySimpleTarget extends SimpleTarget<GlideDrawable> {

        public MySimpleTarget(int width, int height) {
            super(width, height);
        }

        @Override
        public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
            mImageView.setImageDrawable(resource.getCurrent());
        }
    }

三、ViewTarget

在上面一節(jié)中,我們展示了如何通過設(shè)置回調(diào)來獲得最終的Bitmap,但是上面的方法就是有一個缺陷:回調(diào)中只能拿到最終請求到的資源。我們需要持有View的全局對象,這樣才能在收到回調(diào)之后更新它,并且,Glide無法根據(jù)View的實際寬高來決定緩存圖片的大小。
ViewTarget就提供了這樣一種方案:我們在構(gòu)造Target時就傳入自定義的View,這樣在回調(diào)時就可以通過它來更新UI。
它的原理其實和我們開頭說到的傳入ImageView的原理類似,就是通過傳入Target的方式,但是ViewTarget會持有需要更新的View實例,這樣在回調(diào)時候,我們就能執(zhí)行自己需要的操作了,下面是使用ViewTarget的例子:
首先,定義一個自定義的View

public class CustomView extends LinearLayout {

    private ImageView mImageView;
    private TextView mTextView;

    public CustomView(Context context) {
        super(context);
    }
    public CustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        init();
    }

    private void init() {
        mTextView = (TextView) findViewById(R.id.tv_custom_result);
        mImageView = (ImageView) findViewById(R.id.iv_custom_result);
    }

    public void setResult(Drawable drawable) {
        mTextView.setText("load success");
        mImageView.setImageDrawable(drawable);
    }
}

在布局當(dāng)中這么定義它:

    <com.example.lizejun.repoglidelearn.CustomView
        android:id="@+id/cv_result"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:id="@+id/tv_custom_result"
            android:layout_width="match_parent"
            android:layout_height="30dp"
            style="@style/style_tv_normal"/>
        <ImageView
            android:id="@+id/iv_custom_result"
            android:layout_width="200dp"
            android:layout_height="200dp" />
    </com.example.lizejun.repoglidelearn.CustomView>

之后,我們定義一個ViewTarget,并加載它:

    public void loadViewTarget(View view) {
        CustomView customView = (CustomView) findViewById(R.id.cv_result);
        MyViewTarget myViewTarget = new MyViewTarget(customView);
        Glide.with(this)
                .load(R.drawable.book_url)
                .into(myViewTarget);
    }

    private class MyViewTarget extends ViewTarget<CustomView, GlideDrawable> {

        public MyViewTarget(CustomView customView) {
            super(customView);
        }

        @Override
        public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
            view.setResult(resource.getCurrent());
        }
    }

它的整個步驟為:

  • 首先獲得這個自定義View實例。
  • 之后把這個自定義View作為ViewTarget的構(gòu)造函數(shù)的參數(shù),新建一個ViewTarget實例。
  • 把這個ViewTarget通過into()方法傳給Glide
  • 等待Glide請求完畢,那么會回調(diào)ViewTarget中的onResourceReady方法,該Target中有我們傳入的自定義View,這樣,我們就可以調(diào)用這個自定義View內(nèi)部的方法。

四、小結(jié)

  • 從繼承樹上來看,SimpleTargetViewTarget是層次最低的可實現(xiàn)類,也是我們平時開發(fā)中比較常用的類。
  • 這兩者的區(qū)別就是ViewTarget內(nèi)部的實現(xiàn)更加復(fù)雜,它會持有View的引用,并通過內(nèi)部的SizeDeterminer計算View的寬高來提供給Glide作為參考,SimpleTarget則不會去處理這些邏輯,我們需要手動的指定一個寬高,所以,我們需要根據(jù)不同的使用場景來決定繼承于哪個Target來實現(xiàn)自己的業(yè)務(wù)邏輯。
  • 除了SimpleTargetViewTarget,Glide還提供了繼承于它們的Target來簡化我們的操作。例如,更新通知欄和桌面插件,從源碼來看,它們是繼承于SimpleTarget,其最基本的原理和我們自定義SimpleTarget都是相同的,只是在回調(diào)里面調(diào)用AppWidgetManager/NotificationManager增加了更新相應(yīng)組件的操作。在這里就不多介紹了,有需要了解的可以看下面這篇文章:

https://futurestud.io/tutorials/glide-loading-images-into-notifications-and-appwidgets

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,094評論 25 709
  • 零、前言 本文所使用的Glide版本為3.7.0如果需要使用V4的最新版本請參考Glide V4使用指南 一、簡介...
    MrTrying閱讀 204,617評論 36 255
  • 一、簡介 在泰國舉行的谷歌開發(fā)者論壇上,谷歌為我們介紹了一個名叫Glide的圖片加載庫,作者是bumptech。這...
    天天大保建閱讀 7,762評論 2 28
  • 先給大家講一個故事吧: 一位毛拉,也就是牧師,進入講堂,準備布道。講堂里面除了一位坐在前排的年輕男子空空如也。毛拉...
    明睿希燦閱讀 592評論 0 0
  • 國立臺灣大學(xué)社會學(xué)系教授 美國耶魯大學(xué)社會學(xué)博士 林國明 在臺大畢業(yè)典禮的發(fā)言 社會學(xué)知識,有三個要避免的危險...
    被灌醉的小丑閱讀 737評論 0 0

友情鏈接更多精彩內(nèi)容