- 在一个 Gradle 项目中在你的 build.gradle中添加下面这行代码:
compile 'com.github.bumptech.glide:glide:+'
- 从一个 URL 中加载图片
就像 Picasso, Glide 库是使用流接口(fluent interface)。对一个完整的功能请求,Glide 建造者要求最少有三个参数。-
with(Context context) - 对于很多 Android API 调用,Context 是必须的。Glide 在这里也一样
-
load(String imageUrl) - 这里你可以指定哪个图片应该被加载,同上它会是一个字符串的形式表示一个网络图片的 URL
-
into(ImageView targetImageView)你的图片会显示到对应的 ImageView 中。
-
ImageView targetImageView = (ImageView) findViewById(R.id.imageView);
String internetUrl = "http://i.imgur.com/DvpvklR.png";
Glide
.with(context)
.load(internetUrl)
.into(targetImageView);
- 从资源中加载图片
- 从文件中加载
当你让用户选择一张照片去显示图像(比如画廊)这可能会比较有用。该参数只是一个文件
对象。
//这个文件可能不存在于你的设备中。然而你可以用任何文件路径,去指定一个图片路径。
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "Running.jpg");
Glide .with(context) .load(file) .into(imageViewFile);
- 从 Uri 中加载图片
Glide 的一个优势:缓存
Glide 的缓存实现是基于 Picasso,当加载图片时,Glide 使用3个来源:内存,磁盘和网络(从最快到最慢排序)。
占位符和渐现动画
Glide 的流式接口只需要调用 .placeHolder()用一个 drawable(resource) 引用,Glide 将会显示它作为一个占位符,直到你的实际图片准备好。
Glide
.with(context)
.load(UsageExampleListViewAdapter.eatFoodyImages[0])
.placeholder(R.mipmap.ic_launcher) // 也可以是一个drawable
.into(imageViewPlaceholder);
不能设置一个网络 url 作为占位符,因为这也会被去请求加载的。App 资源和 drawable 能保证可用和可访问的。然而,作为 load()方法的参数,Glide 接受所有值。
当App 尝试从一个网站去加载一张图片,但由于某些原因加载失败,使用错误占位符:.error(),在大多数情况下使用占位符,来指明图片不能被加载已经足够了。
Glide
.with(context)
.load("http://futurestud.io/non_existing_image.png")
.placeholder(R.mipmap.ic_launcher) // 也可以是一个drawable
.error(R.mipmap.future_studio_launcher) // 如果图片不能加载就会显示
.into(imageViewError);
error()接受的参数只能是已经初始化的 drawable 对象或者指明它的资源。
Glide 使用标准的淡入淡出动画,这是默认激活的。如果你想要如强制 Glide 显示一个淡入淡出动画,你必须调用另外一个建造者:
Glide
.with(context)
.load("http://futurestud.io/non_existing_image.png")
.placeholder(R.mipmap.ic_launcher) // 也可以是一个drawable
.error(R.mipmap.future_studio_launcher) // 如果图片不能加载就会显示
.
.into(imageViewError);
crossFade()方法还有另外重载方法 .crossFade(int duration)。如果你想要去减慢(或加快)动画,随时可以传一个毫秒的时间给这个方法。动画默认的持续时间是 300毫秒。
用 resize(x,y) 调整图片大小
Glide 自动限制了图片的尺寸在缓存和内存中,并给到 ImageView需要的尺寸。如果图片不会自动适配到 ImageView,调用 override(horizontalSize, verticalSize) 。这将在图片显示到 ImageView之前重新改变图片大小。
Glide
.with(context)
.load(UsageExampleListViewAdapter.eatFoodyImages[0])
.override(600, 200) // 重新改变图片大小成这些尺寸(像素).不关心长宽比
.into(imageViewResize);
当你还没有目标 view 去知道尺寸的时候,这个选项也可能是有用的。比如,如果 App 想要在闪屏界面预热缓存,它还不能测量 ImageView的尺寸。然而,如果你知道这个图片多少大,用 override 去提供明确的尺寸。
缩放图像
- CenterCrop
CenterCrop()是一个裁剪技术,即缩放图像让它填充到 ImageView
界限内并且裁剪额外的部分。ImageView可能会完全填充,但图像可能不会完整显示。
Glide
.with(context)
.load(UsageExampleListViewAdapter.eatFoodyImages[0])
.override(600, 200) // 重新改变图片大小成这些尺寸(像素)比
.centerCrop() // 这种裁剪技术缩放图像,使其填充请求的边界,然后裁剪额外的。
.into(imageViewResizeCenterCrop);
- FitCenter
fitCenter()是裁剪技术,即缩放图像让图像都测量出来等于或小于 ImageView的边界范围。该图像将会完全显示,但可能不会填满整个 ImageView。
Glide
.with(context)
.load(UsageExampleListViewAdapter.eatFoodyImages[0])
.override(600, 200)
.fitCenter()
.into(imageViewResizeFitCenter);
显示 Gif
检查图片加载的是否是一个gif图片,调用一个额外的防区强制 Glide变成一个 Gif asGif()
String gifUrl = "http://i.kinja-img.com/gawker-media/image/upload/s--B7tUiM5l--/gf2r69yorbdesguga10i.gif";
Glide
.with( context )
.load( gifUrl )
.asGif()
.error( R.drawable.full_cake )
.into( imageViewGif );
如果这个 gifUrl 不是一个 Gif,.error()回调被调用并且错误占位符被显示。
Gif 转为 Bitmap
如果你仅仅想要显示 Gif 的第一帧,你可以调用 asBitmap()去保证其作为一个常规的图片显示,即使这个 URL 是一个 Gif。
Glide
.with( context )
.load( gifUrl )
.asBitmap()
.into( imageViewGifAsBitmap );
内存缓存
Glide 通过使用默认的内存和磁环缓存去避免不必要的网络请求。调用了 .skipMemoryCache(true)去明确告诉 Glide 跳过内存缓存。可以用 .diskCacheStrategy()方法为 Glide 改变磁盘缓存的行为,如果要为一个请求禁用磁盘缓存。使用枚举 DiskCacheStrategy.NONE。
作为参数。
Glide
.with( context )
.load( eatFoodyImages[0] )
.diskCacheStrategy( DiskCacheStrategy.NONE )
.skipMemoryCache( true )
.into( imageViewInternet );
Glide 缓存了原始图像,全分辨率图像和另外小版本的图像。对于 .diskCacheStrategy()方法来说不同的枚举参数的意义:
- DiskCacheStrategy.NONE什么都不缓存
- DiskCacheStrategy.SOURCE仅仅只缓存原来的全分辨率的图像。
- DiskCacheStrategy.RESULT仅仅缓存最终的图像,即降低分辨率后的(或者是转换后的)(默认行为)
- DiskCacheStrategy.ALL缓存所有版本的图像
如果有一张图片,将会经常操作处理,并做了一堆不同的版本,对其有意义的仅仅是缓存原始分辨率图片,用 DiskCacheStrategy.SOURCE。
图片请求的优先级
Priority (优先级)枚举
- Priority.LOW
- Priority.NORMAL
- Priority.HIGH
- Priority.IMMEDIATE
你正在实现一个信息详情页面,有一个英雄图片在顶部,和较小的图片在底部。对于最好的用户体验来说,英雄图片首先需要被加载。因此,我们用 Priority.HIGH
来处理它。理论上说,这应该够了,但是为了让这个实例增加点趣味,我们也将底层图像分配给低优先级,用 .priority(Priority.LOW)
调用:
private void loadImageWithHighPriority() {
Glide
.with( context )
.load( UsageExampleListViewAdapter.eatFoodyImages[0] )
.priority( Priority.HIGH )
.into( imageViewHero );
}
private void loadImagesWithLowPriority() {
Glide
.with( context )
.load( UsageExampleListViewAdapter.eatFoodyImages[1] )
.priority( Priority.LOW )
.into( imageViewLowPrioLeft );
Glide
.with( context )
.load( UsageExampleListViewAdapter.eatFoodyImages[2] )
.priority( Priority.LOW )
.into( imageViewLowPrioRight );
}
缩略图
用原图的1/10作为缩略图
Glide
.with(this)
.load(UsageExampleGifAndVideos.gifUrl)
.thumbnail(0.1f)
.into(imageView2);
用其它图片作为缩略图
DrawableRequestBuilder<String> thumbnailRequest =
Glide
.with(this)
.load(R.drawable.news);
Glide
.with(this)
.load(UsageExampleGifAndVideos.gifUrl)
.thumbnail(thumbnailRequest)
.into(imageView3);
Glide 中的回调:Targets
Glide 提供了一个用 Targets的简单的方式去接受图片资源的 Bitmap。Targets 是没有任何别的回调,它在 Glide 做完所有的加载和处理之后返回结果。
- SimpleTarget:
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() ) // 如果你target 是独立于应用的 activity 生命周期,如果请求需要在 activity 生命周期之外去做时,才用这样的代码
.load(eatFoodyImages[1])
.asBitmap()
.into(target2);
}
- ViewTarget:
Glide 可以用 ViewTarget加载图片到自定义 view 中。
首先自定义 View,它继承自 FrameLayout并内部使用了一个 ImageView以及覆盖了一个 TextView。
public class TargetView extends FrameLayout {
ImageView iv;
TextView tv;
public void initialize(Context context) {
inflate(context, R.layout.custom_view_target, this);
iv = (ImageView) findViewById(R.id.custom_view_image);
tv = (TextView) findViewById(R.id.custom_view_text);
}
public TargetView(Context context, AttributeSet attrs) {
super(context, attrs);
initialize(context);
}
public TargetView(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() {
TargetView customView = (TargetView) findViewById( R.id.custom_view );
ViewTarget viewTarget = new ViewTarget<TargetView, 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 );
}
-
加载图片到 Notifications(重点)----NotificationTarget
首先编写通知栏
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="2dp">
<ImageView
android:id="@+id/remoteview_notification_icon"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginRight="2dp"
android:layout_weight="0"
android:scaleType="centerCrop"/> //按比例扩大图片的size居中显示,使得图片长(宽)等于或大于View的长(宽)
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/remoteview_notification_headline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end" //内容过长加省略号的属性,省略号在结尾
android:singleLine="true"
android:textSize="12sp"/>
<TextView
android:id="@+id/remoteview_notification_short_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:paddingBottom="2dp"
android:singleLine="true"
android:textSize="14sp"
android:textStyle="bold"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
创建一个自定义通知
final RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.remoteview_notification);
rv.setImageViewResource(R.id.remoteview_notification_icon, R.mipmap.future_studio_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(context)
.setSmallIcon(R.mipmap.future_studio_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) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(NOTIFICATION_ID, notification);
上述创建了三个重要的对象,notification和 RemoteViews以及常量 NOTIFICATION_ID。利用这些去创建一个通知 target。
private NotificationTarget notificationTarget;
...
notificationTarget = new NotificationTarget(
context,
rv,
R.id.remoteview_notification_icon,
notification,
NOTIFICATION_ID);
调用 Glide,将 target 作为 .into()的参数。
Glide
.with( context.getApplicationContext() )
.load( eatFoodyImages[3] )
.asBitmap()
.into( notificationTarget );
Transformations(转换)
在图片被显示之前,transformations(转换) 可以被用于图像的操作处理。图片的任意属性:颜色、尺寸、范围、颜色、像素位置等等。下面的库它为 Glide 转换提供了多种多样的实现:
glide-transformations
用 animate() 自定义动画
创建自己的 XML 动画,比如一个小的缩放动画,图片刚开始小的,然后逐渐增大到原尺寸。
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">
<scale
android:duration="@android:integer/config_longAnimTime"
android:fromXScale="0.1"
android:fromYScale="0.1"
android:pivotX="50%"
android:pivotY="50%" //这两个属性控制着View对象的支点位置,围绕这个支点进行旋转和缩放变换处理
android:toXScale="1" //缩放
android:toYScale="1"/>
</set>
这两个动画可以添加到Glid中
Glide
.with( context )
.load( eatFoodyImages[0] )
.animate( android.R.anim.slide_in_left ) //或者R.anim.zoom_in
.into( imageView1 );
-
集成网络栈
集成 OkHttp 作为你给 Glide 的网络库,在build.gradle依赖中添加下面这两行代码:
dependencies {
// your other dependencies
// ...
//Glide
compile 'com.github.bumptech.glide:glide:3.6.1'
// Glide's OkHttp Integration
compile 'com.github.bumptech.glide:okhttp-integration:1.3.1@aar'
compile 'com.squareup.okhttp:okhttp:2.5.0'
}
-
用 Module 自定义 Glide
为了定制 Glide,你需要去实现一个GlideModule接口的公共类。
public class SimpleGlideModule implements GlideModule {
@Override
public void applyOptions(Context context, GlideBuilder builder) {
// todo
}
@Override
public void registerComponents(Context context, Glide glide) {
// todo
}
}
在 AndroidManifest.xml的 <application>标签内去声明这个刚刚创建的 Glide module。
<manifest
...
<application>
<meta-data
android:name="io.futurestud.tutorials.glide.glidemodule.SimpleGlideModule"
android:value="GlideModule" />
...
</application>
</manifest>
android:name属性是包名+类名的形式。
要看第一个方法applyOptions(Context context, GlideBuilder builder),可以在这个方法里去调 GlideBuilder中可用的方法。
- setMemoryCache(MemoryCache memoryCache)
- setBitmapPool(BitmapPool bitmapPool)
- setDiskCache(DiskCache.Factory diskCacheFactory)
- setDiskCacheService(ExecutorService service)
- setResizeService(ExecutorService service)
- setDecodeFormat(DecodeFormat decodeFormat)
可以通过这些方法改变磁盘缓存,内存缓存等等。
示例:增加 Glide 的图片质量
在 Android 中有两个主要的方法对图片进行解码:ARGB8888 和 RGB565。前者为每个像素使用了 4 个字节,后者仅为每个像素使用了 2 个字节。ARGB8888 的优势是图像质量更高以及能存储一个 alpha 通道。Glide 默认使用低质量的 RGB565。可以使用 Glide module 方法去改变解码规则。
public class SimpleGlideModule implements GlideModule {
@Override
public void applyOptions(Context context, GlideBuilder builder) {
builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888);
}
@Override
public void registerComponents(Context context, Glide glide) {
// nothing to do here
}
}
-
接受自签名证书的 HTTPS
可能是当你的图片从服务端获取时,是使用HTTPS,且是自签名的(self-signed)。这时 Glide 不会下载或显示图片了,因为自签名的证书被认为是一个安全的问题。
参考:
Glide系列教程
网友评论