首先,咱們回顧一下Glide
的基本用法,咱們的最後一步都是調用into(ImageView imageView)
,經過斷點,咱們能夠看到正是這一步觸發了圖片的請求: android
ImageView
最終會經過
buildTarget
方法,封裝在
GlideDrawableImageViewTarget
當中,而後調用
GenericRequestBuilder#into
方法發起請求,
Glide
一直跟蹤這個
Target
,並在得到圖片資源以後,通知
Target
來更新它內部持有的
ImageView
的引用。 這個過程就好像是咱們平時請求網絡時,會傳入一個
Callback
,等到異步的操做執行完畢後,經過
Callback
傳回請求的資源來更新
UI
。 經過源碼,能夠看到和
Target
相關的類有:
Target
BaseTarget
SimpleTarget
:AppWidgetTarget
、PreloadTatget
、NotificationTarget
ViewTarget
ImageViewTarget
:GlideDrawableImageViewTarget
、BitmapImageViewTarget
、DrawableImageViewTarget
今天這篇文章,咱們就來學習一下SimpleTarget
和ViewTarget
的用法,主要參考了下面連接中的文章:緩存
https://futurestud.io/tutorials/glide-callbacks-simpletarget-and-viewtarget-for-custom-view-classes
bash
SimpleTarget
SimpleTarget
能夠看做是請求的回調,咱們在回調當中進行處理,而不是傳入ImageView
讓Glide
去負責更新。服務器
先看一下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
方法傳入。這樣當Glide
去服務器請求圖片成功以後,它會把請求到的圖片資源做爲GlideDrawable
傳遞回來,你可使用這個GlideDrawable.getCurrent()
進行本身想要的操做。 關於上面SimpleTarget
的使用須要知道兩點:app
SimpleTarget
定義成了局部變量,那麼它頗有可能會被回收,一旦它被回收,那麼咱們收不到任何的回調了。with
中傳入了Activity
的Context
,那麼Glide
就會監聽Activity
生命週期的變化,當Activity
退到後臺以後,中止該請求。若是你但願它獨立於Activity
的生命週期,那麼須要傳入一個Application
的Context
。當咱們傳入ImageView
時,Glide
會根據ImageView
的大小來自動調整緩存的圖片資源大小,而當咱們使用Target
的時候,並無提供這個條件來給Glide
,所以,爲了縮短處理時間和減小內存,咱們能夠按下面的方法來指定緩存的大小:異步
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
在上面一節中,咱們展現瞭如何經過設置回調來得到最終的Bitmap
,可是上面的方法就是有一個缺陷:回調中只能拿到最終請求到的資源。咱們須要持有View
的全局對象,這樣才能在收到回調以後更新它,而且,Glide
沒法根據View
的實際寬高來決定緩存圖片的大小。 ViewTarget
就提供了這樣一種方案:咱們在構造Target
時就傳入自定義的View
,這樣在回調時就能夠經過它來更新UI
。 它的原理其實和咱們開頭說到的傳入ImageView
的原理相似,就是經過傳入Target
的方式,可是ViewTarget
會持有須要更新的View
實例,這樣在回調時候,咱們就能執行本身須要的操做了,下面是使用ViewTarget
的例子: 首先,定義一個自定義的View
:ide
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);
}
}
複製代碼
在佈局當中這麼定義它:函數
<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
的構造函數的參數,新建一個ViewTarget
實例。ViewTarget
經過into()
方法傳給Glide
。Glide
請求完畢,那麼會回調ViewTarget
中的onResourceReady
方法,該Target
中有咱們傳入的自定義View
,這樣,咱們就能夠調用這個自定義View
內部的方法。SimpleTarget
和ViewTarget
是層次最低的可實現類,也是咱們平時開發中比較經常使用的類。ViewTarget
內部的實現更加複雜,它會持有View
的引用,並經過內部的SizeDeterminer
計算View
的寬高來提供給Glide
做爲參考,SimpleTarget
則不會去處理這些邏輯,咱們須要手動的指定一個寬高,因此,咱們須要根據不一樣的使用場景來決定繼承於哪一個Target
來實現本身的業務邏輯。SimpleTarget
和ViewTarget
,Glide
還提供了繼承於它們的Target
來簡化咱們的操做。例如,更新通知欄和桌面插件,從源碼來看,它們是繼承於SimpleTarget
,其最基本的原理和咱們自定義SimpleTarget
都是相同的,只是在回調裏面調用AppWidgetManager/NotificationManager
增長了更新相應組件的操做。在這裏就很少介紹了,有須要瞭解的能夠看下面這篇文章:
https://futurestud.io/tutorials/glide-loading-images-into-notifications-and-appwidgets