http://mrfu.me/2016/02/27/Glide_Thumbnails/
目前为止,我们很方便的使用 Glide 建造者去加载图片到 ImageView 中了。Glide 隐藏了一大堆复杂的在后台的场景。Glide 做了所有的网络请求和处理在后台线程中,一旦结果准备好了之后,切回到 UI 线程然后更新 ImageView。
在这篇博客中,我们假定 ImageView 不再是图像的最后一步。我们只要 Bitmap 本身。Glide 提供了一个用 Targets 的简单的方式去接受图片资源的 Bitmap。Targets 是回调函数,它在 Glide 做完所有的加载和处理之后返回结果。
Glide 提供了各种的 targets 并且每个都有其明确的目的。我们将在接下来的几节中通过使用它们。让我们从 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 );
}
这段代码的第一部分创建了一个字段对象,声明了一个方法,即一旦 Glide 已加载并处理完图像,它将被调用。这个回调方法传了 Bitmap 作为一个参数。你之后便可以使用这个 Bitmap 对象,无论你要怎样用它。
这段代码的第二部分是我们如何通过 Glide 用 targets:和 ImageView 用法完全相同的!你既可以传一个 Target 也可以传一个 ImageView 参数给 .into() 方法。Glide 自己将会处理并返回结果给任何一个。这里有一些不同的是,我们添加了 .asBitmap(),它强制 Glide 去返回一个 Bitmap 对象。记住,Glide 也可以加载 Gif 或 video 的。为了防止 target 的冲突(我们需要 Bitmap) 和未知资源在网络背后的 URL(可能是一个 Gif),我们可以调用 .asBitmap() 告诉 Glide 我们需要一个图像。
除了知道如何实现一个简单版本的 Glide 的 Target 回调系统,你要学会额外两件事。
首先是 SimpleTarget 对象的字段声明。从技术上来说,Java/Android 会允许你在 .into() 方法中去声明 target 的匿名内部类。然而,这大大增加了这样一个可能性:即在 Glide 做完图片请求之前, Android 垃圾回收移除了这个匿名内部类对象。最终这可能会导致一个情况,当图像加载完成了,但是回调再也不会被调用。所请确保你所声明的回调对象是作为一个字段对象的,这样你就可以保护它避免被邪恶的 Android 垃圾回收机制回收 ;
第二个关键部分是 Glide 建造者中这行:.with(context)。 这里的问题实际是 Glide 的功能:当你传了一个 context(例如是当前应用的 activity),Glide 将会自动停止请求当 activity 已经停止的时候。这整合到了应用的生命周期中通常是非常有帮助的,但是有时工作起来是困难的,如果你的 target 是独立于应用的 activity 生命周期。这里的解决方案是用 application 的 context: .with(context.getApplicationContext))。当应用资深完全停止时,Glide 才会杀死这个图片请求。请求记住,再说一次,如果你的请求需要在 activity 生命周期之外去做时,才用下面这样的代码:
private void loadImageSimpleTargetApplicationContext() {
Glide
.with( context.getApplicationContext() ) // safer!
.load( eatFoodyImages[1]
.asBitmap()
.into( target2 );
}
另一个潜在的问题是,target 没有指明大小。如果你传一个 ImageView 作为参数给 .into(),Glide 将会用 ImageView 的大小去限制图像的大小。比如说,如果加载的图片是 1000x1000 像素的,但是 ImageView 只有 250x250 像素,Glide 将会减少图片的尺寸去节省时间和内存。很显然,在和 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 );
}
我们不能直接使用 ImageView 的原因可能是多种多样的。我们已经向你展示如何去接收一个 Bitmap。现在我们要更进一步。假设你有一个 Custom View。Glide 并不支持加载图片到自定义 view 中,因为并没有方法知道图片应该在哪里被设置。然而,Glide 可以用 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 );
}
}
你不能使用常规的 Glide 的方法 .into(),因为我们的自定义 view 并不继承自 ImageView。因此,我们必须创建一个 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 回调方法中,我们使用我们创建的方法 setImage(Drawable drawable)
在自定义 view 类中去设置图片。另外确保你注意到我们必须在 ViewTarget 的构造函数中传递我们自定义 view 作为参数:new ViewTarget<FutureStudioView, GlideDrawable>(customView)
。
这应该涵盖了所有你需要的自定义 view。你也可以在回调中添加额外的工作。如,我们可以分析传入的 Bitmap 的主要的颜色并设置十六进制值给 TextView。但我们相信你应该已经有一些想法了。
在这篇相当长的博客中,你已经了解了在 Glide 中 target 的基本原理。你已经学会了如何访问图片的 Bitmap 以及如何将图片加载到你自定义的 view 中。我们错过什么了吗?让在评论中让我们知晓!
下周,我们将继续 target 的实例,当我们看如何加载图像到通知中以及应用程序窗口小部件里。