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。现在,我们将更深入学习。假设你有个自定义的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中。可以在评论中告诉我们我们忽略了什么。

后面的文章,我们将要继续通过例子介绍target如何向通知栏和桌面小控件加载图片。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容

  • 一、简介 在泰国举行的谷歌开发者论坛上,谷歌为我们介绍了一个名叫Glide的图片加载库,作者是bumptech。这...
    天天大保建阅读 7,451评论 2 28
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,424评论 25 707
  • 零、前言 本文所使用的Glide版本为3.7.0如果需要使用V4的最新版本请参考Glide V4使用指南 一、简介...
    MrTrying阅读 203,860评论 36 255
  • 当你看到孩子成绩时,无论好坏,请想想:每个孩子都是一颗花的种子,只不过花期不同。有的花,一开始就灿烂绽放;有的花,...
    钱蓉蓉阅读 933评论 0 1
  • 李菁《摄影梦想课堂》的摄影学习公众号很棒。因为有许多的学员在一起学,共同进步,这样整理出来又使大家看到优缺点,而且...
    窗花阅读 380评论 0 0