玩转Glide的Target对象

概述

前两天在看项目源码时候突然看见这个Target对象,场景是这样的,我们通常在Activity的背景中加一张图片,是在xml的根布局中加一张本地的资源图片,而这个项目不是这样的,如下是它的实现方式:
这里写图片描述
我们可以看见首先声明了一个ViewTarget对象,然后在匿名函数的回调中设置背景Drawable,这个字段的调用是通过Glide调用的,我们通常into的时候是传一个imageView控件,而这里传入的是viewTarget。当时就感觉很奇怪为什么要这样做?设置背景为啥要这样做?

一番搜索终于有点眉目了,项目中加载图片是本地的,并且那个控件是继承View的,而如果要从网上加载一张图片,我们用Glide的话是into进一个imageview,而如果想into一个继承自View的控件,我们就需要一个Target对象适配了,当然Target还可以干很多其他的事,并不只是这些。所以我们从这里可以知道,这段代码可以非常简单的实现了一个这样的目标,那就是我们可以加载一张网上图片,并且可以设置给View以及其子类。

接下来分别看下几个我了解到的Target对象子类实现:SimpleTarget,ViewTarget,NotificationTarget,AppWidgetTarget。

Glide提供了各种的Targets并且每种都有其自己的特点。


SimpleTarget

通常的时候我们需要一张图片的Bitmap,Glide提供了一个Target去接收图片的资源的Bitmap,当Glide做完图片的下载加载和其他处理之后回调Target来接收返回结果。

看实例:

//声明一个SimpleTarget
private SimpleTarget target = new SimpleTarget<Bitmap>(400,400) {

        @Override
        public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
            //给一个View设置Bitmap
            iv_pic.setImageBitmap(resource);
        }
    };

//Glide调用处理
Glide.with(getApplicationContext()).load(url).asBitmap().into(target);

这段代码第一部分定义了一个Target,用泛型指定为Bitmap类型,并指定接收Bitmap的宽高为400,400,这只是一个随意设置的值,第二部分的代码和以前加载ImageView的一样,只不过这里换成Target。需要注意的是,这里调用了asBitmap()强制将下载下来的资源转换为Bitmap,因为通过Glide加载的可能是gif或者video,为了防止回调的target冲突。当你获取到bitmap之后,你就可以干任何事情了。

指定target的尺寸

有时候我们自定义的view是使用wrap_content设置宽高的,这样从网上下载下来的图片设置给View是多大就是多大,有时候我们并不需要这么大的图片,我们只需要能够在屏幕上可以看见这张图就可以了。这时候我们就需要压缩下载的图片,通过指定的SimpleTarget的width和height,Glide就会去减小图片的大小,就可以达到压缩图片的目的,减少下载图片的时间,这样可以节约内存。

关注Target

从别人的博客里看见了这段话,拿来借鉴下:
这里写图片描述
地址

ViewTarget

这个Target的使用场景可以这样,假如我们自定义了一个View,并且我们想给这个自定义控件设置图片,而Glide并没有这样的方法去给View设置图片。此时我们就可以使用ViewTarget轻松实现。

看下实例代码:

//简单自定义View
public class FutureStudioView extends FrameLayout {
    ImageView iv;
    public void initialize(Context context) {
        inflate( context, R.layout.custom_view_futurestudio, this );

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

    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 );
    }

    public void setImage(Bitmap bitmap){
        iv = (ImageView) findViewById( R.id.custom_view_image );
        iv.setImageBitmap(bitmap);
    }
}

//定义ViewTarget
private ViewTarget viewTarget ;
viewTarget = new ViewTarget<FutureStudioView, Bitmap>(fsv) {
            @Override
            public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
                this.view.setImage(resource);
            }
        };

//Glide加载
Glide.with(context).load(url).asBitmap().into(viewTarget);

我们可以看见ViewTarget接收两个泛型参数,第一个是从View实现的子类都可以,而第二个是资源对象,比如Bitmap或者GlideDrawable,它是Drawable的子类。并且ViewTarget的实现需要传一个参数,它是第一个泛型参数的具体实现类。而在回调方法中this.view通过源码可以看见就是代表FutureStudioView这个自定义的View类型。

NotificationTarget

在使用通知的时候,我们一般会使用图标,比如这样:
这里写图片描述
如果图片要从网上获取,然后再在通知栏上显示出来,这样就不太容易实现,我们可以通过前面的SimpleTarget实现,但是也有更好的方法就是通过NotificationTarget对象。

接下来就看一个自定义从网上获取资源图片的通知栏实例:

1.首先我们要定义一个自定义布局界面,界面蛮简单就不贴代码了
2.然后通过RemoteViews加载这一个布局文件

RemoteViews rv = new RemoteViews(getPackageName(), R.layout.remoteview_notification);

3.构建通知

rv.setImageViewResource(R.id.remoteview_notification_icon, R.mipmap.ic_launcher);

        rv.setTextViewText(R.id.remoteview_notification_headline, "Headline");
        rv.setTextViewText(R.id.remoteview_notification_short_message, "Short Message");

        // build notification
        NotificationCompat.Builder mBuilder =
                new NotificationCompat.Builder(this)
                        .setSmallIcon(R.mipmap.ic_launcher)
                        .setContentTitle("Content Title")
                        .setContentText("Content Text")
                        .setContent(rv)
                        .setPriority( NotificationCompat.PRIORITY_MIN);

        final Notification notification = mBuilder.build();

        // set big content view for newer androids
        if (android.os.Build.VERSION.SDK_INT >= 16) {
            notification.bigContentView = rv;
        }

        NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        mNotificationManager.notify(1, notification);

4.创建NotificationTarget对象

上面代码片段为我们创建了三个重要的对象, notification 和 RemoteViews 以及常量 NOTIFICATION_ID,也就是那个1。我们需要这些去创建一个通知 target。

NotificationTarget notificationTarget = new NotificationTarget(this, rv, R.id.remoteview_notification_icon,notification, 1);

5.Glide调用
调用就和前面一样简单了

        Glide.with(getApplicationContext()).load(url).asBitmap().into(notificationTarget);

看下实现结果
这里写图片描述

如此就完成了在通知栏显示一个网络图片。

AppWidgetTarget

窗口小部件在我刚初学时确实是一个高大上的东西,它也是android中一个比较常用的部件。看下Target在窗口小部件中的应用。

1.新建一个类继承AppWidgetProvider,然后实现其onUpdate方法

public class FSAppWidgetProvider extends AppWidgetProvider {

    private AppWidgetTarget appWidgetTarget;
    private final static String url = "http://img02.tooopen.com/downs//images/2010/9/16/sy_2010091620583620405.jpg";

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.custom_view_futurestudio);
        appWidgetTarget = new AppWidgetTarget(context, rv, R.id.custom_view_image, appWidgetIds);

        Glide.with(context.getApplicationContext())
                .load(url)
                .asBitmap()
                .into(appWidgetTarget);

        pushWidgetUpdate(context, rv);
    }

    public static void pushWidgetUpdate(Context context, RemoteViews rv){
        ComponentName myWidget = new ComponentName(context, FSAppWidgetProvider.class);
        AppWidgetManager manager = AppWidgetManager.getInstance(context);
        manager.updateAppWidget(myWidget, rv);
    }
}

2.在清单文件中注册

<receiver android:name=".FSAppWidgetProvider">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>
            <meta-data android:name="android.appwidget.provider"
                android:resource="@xml/widget_provider"/>
        </receiver>

3.xml中widget_provider文件

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="180dp"
    android:minHeight="45dp"
    android:previewImage="@mipmap/ic_launcher"
    android:initialLayout="@layout/custom_view_futurestudio"
    android:resizeMode="horizontal|vertical"
    android:widgetCategory="home_screen">

</appwidget-provider>

custom_view_futurestudio为窗口小部件的布局文件

4.实现效果
这里写图片描述


最后

关于Target的用法,并不只是这几个,还有更多的用法,这里就不介绍了。

参考了这篇文章Glide 入门到精通之十——加载图片到通知栏和应用小部件中Glide 入门到精通之九——SimpleTarget 和 ViewTarget 用于自定义视图类,该博主还有一系列其他文章,可以值得学习下。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值