Glide,作为一个当下主流的专门用于图片加载的框架,以其简明的语法和高效的性能而闻名。有关Glide的官方说明,可以参考下面这段Glide的中文文本说明,取自于Glide v4 快速高效的Android图片加载库,即:
Glide是一个快速高效的Android图片加载库,注重于平滑的滚动。Glide提供了易用的API,高性能、可扩展的图片解码管道(decode pipeline),以及自动的资源池技术。
Glide 支持拉取,解码和展示视频快照,图片,和GIF动画。Glide的Api是如此的灵活,开发者甚至可以插入和替换成自己喜爱的任何网络栈。默认情况下,Glide使用的是一个定制化的基于HttpUrlConnection的栈,但同时也提供了与Google Volley和Square OkHttp快速集成的工具库。
虽然Glide的主要目标是让任何形式的图片列表的滚动尽可能地变得更快、更平滑,但实际上,Glide几乎能满足你对远程图片的拉取/缩放/显示的一切需求。
当然,由于Glide被收录到了《第一行代码 Android》中,我也很早地就接触到了这个框架。作为第一个接触到的图片加载框架,我对它的印象也比较深。趁着这次框架学习之时,我便想要再度复习这个已经因为长时不用而有些陌生的框架。
说实话,最开始在学习Android的时候,我并不知道使用图片加载的系列框架会带来什么好处,因为原生的Android就已经提供了相应的api语句。当Android的学习愈发深入后,才深刻理解到这些框架的益处。如果只用原生的api语句实现图片加载,可能会出现各种意想不到的问题。而图片加载框架的引入,解决了包括三级缓存、ANR等一系列优化问题。正因如此,我们更需要学习该系列框架的使用,为以后的项目开发打好扎实的基础。
话不多活,让我们马上开始Glide的学习吧。
根据官方文档的说明,Glide的特性可以分由三个方面进行讲解:
API
Glide 使用简明的流式语法API,这是一个非常棒的设计,因为它允许你在大部分情况下一行代码搞定需求:
Glide.with(fragment)
.load(url)
.into(imageView);
这句描述确实不夸张,因为Glide的大部分业务基本上都是倚靠这行代码就可以实现
性能
Glide 充分考虑了Android图片加载性能的两个关键方面:
为了让用户拥有良好的App使用体验,图片不仅要快速加载,而且还不能因为过多的主线程I/O或频繁的垃圾回收导致页面的闪烁和抖动现象。
步骤
Glide使用了多个步骤来确保在Android上加载图片尽可能的快速和平滑:
正因为Glide具有这三方面的优点,于是成为了当下主流的图片加载框架。说实话,它的使用确实相当简单。在接下来的演示环节中,读者就可以感受到。
在使用框架之前,第一步永远都是集成。我们去Glide的GitHub官网上搜索最新版本:Glide,然后修改module下的build.gradle,代码如下:
implementation 'com.github.bumptech.glide:glide:4.11.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
在使用Glide的时候,我们可能需要申请一些权限。修改Manifest.xml,添加相应权限,代码如下:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
这里为了演示Glide提供的最基本的图片加载功能,就使用尽可能简单的业务逻辑。修改activity_main.xml,增加一个ImageView
控件和两个按钮,按钮分别作用与让图片的显示和图片的清除,代码如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical">
<Button
android:id="@+id/btn_load_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="加载图片"/>
<Button
android:id="@+id/btn_unload_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="取消加载"/>
<ImageView
android:id="@+id/iv_standard"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
LinearLayout>
修改MainActivity,首先添加initUI()
方法,用于初始化布局中的三个控件,然后构造一个File对象,将手机中的一张名为test.jpg的图片封装起来(注意:这里获取路径名的api为context.getExternalFilesDir(),而没有用之前的Environment.getExternalStorageState()。这是因为Android X的新特性:作用域存储,即每个应用只能自己的应用路径下存放文件,而不是像之前一样直接在sdcard上,该局api可以获取到的路径为:/storage/emulated/0/Android/data/<包名>/files),另外,实现了两个按钮的点击方法,每个按钮中的方法仅有一行代码,代码如下:
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import java.io.File;
public class MainActivity extends AppCompatActivity {
private ImageView iv_standard;
private Button btn_load_image;
private Button btn_unload_image;
private File mImageFile;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 初始化UI
initUI();
// 为mImageFile赋予实例对象
mImageFile = new File(this.getExternalFilesDir(null) + File.separator + "test.jpg");
// 1.加载图片
loadImage();
// 2.取消图片加载
unloadImage();
}
/**
* 初始化UI
*/
private void initUI() {
iv_standard = findViewById(R.id.iv_standard);
btn_load_image = findViewById(R.id.btn_load_image);
btn_unload_image = findViewById(R.id.btn_unload_image);
}
/**
* 1.加载图片
*/
private void loadImage() {
btn_load_image.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Glide.with(getApplicationContext())
.load(mImageFile)
.into(iv_standard);
}
});
}
/**
* 2.取消图片加载
*/
private void unloadImage(){
btn_unload_image.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Glide.with(getApplicationContext())
.clear(iv_standard);
}
});
}
}
编写完成后,接下来运行程序,可以看到我们刚刚编写好的布局界面,如图所示:
点击“加载图片”按钮,图片就会显示到ImageView
控件上,如图所示:
如果点击“取消加载”按钮,图片就会消失。反复来回点击这两个按钮,就可以控制图片的加载和清除。这样,就实现了Glide最基本的功能:图片加载。
当然,Glide的功能远远不止这个。在下面的小节中,将讲解Glide的一些拓展功能。当然,限于篇幅限制,接下来就只贴出业务逻辑代码和一些简单的说明,就不一一详解了。
// 加载本地图片
File file = new File(getExternalCacheDir() + "/image.jpg");
Glide.with(this).load(file).into(imageView);
// 加载应用资源
int resource = R.drawable.image;
Glide.with(this).load(resource).into(imageView);
// 加载二进制流
byte[] image = getImageBytes();
Glide.with(this).load(image).into(imageView);
// 加载Uri对象
Uri imageUri = getImageUri();
Glide.with(this).load(imageUri).into(imageView);
占位图,目的是为在图片还未加载出来的时候,提前展示给用户的一张图片;
Glide.with(this).load(url).placeholder(R.drawable.loading).into(imageView);
还有一种占位图,作为图片加载失败的另一张图片
Glide.with(this).load(url).placeholder(R.drawable.loading).error(R.drawable.error)
.diskCacheStrategy(DiskCacheStrategy.NONE)//关闭Glide的硬盘缓存机制
.into(imageView);
//DiskCacheStrategy.NONE: 表示不缓存任何内容。
//DiskCacheStrategy.SOURCE: 表示只缓存原始图片。
//DiskCacheStrategy.RESULT: 表示只缓存转换过后的图片(默认选项)。
//DiskCacheStrategy.ALL : 表示既缓存原始图片,也缓存转换过后的图片。
Glide.with(this)
.load(url)
.asBitmap()//只加载静态图片,如果是git图片则只加载第一帧。
.placeholder(R.drawable.loading)
.error(R.drawable.error)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageView);
Glide.with(this)
.load(url)
.asGif()//加载动态图片,若现有图片为非gif图片,则直接加载错误占位图。
.placeholder(R.drawable.loading)
.error(R.drawable.error)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageView);
Glide.with(this)
.load(url)
.placeholder(R.drawable.loading)
.error(R.drawable.error)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.override(100, 100)//指定图片大小
.into(imageView);
这里的不带缓存分为两种情况,即:
不带内存缓存
Glide.with(this)
.load(url)
.skipMemoryCache(true) //传入参数为false时,则关闭内存缓存。
.into(imageView);
不带硬盘缓存
Glide.with(this)
.load(url)
.diskCacheStrategy(DiskCacheStrategy.NONE) //关闭硬盘缓存操作
.into(imageView);
//其他参数表示:
//DiskCacheStrategy.NONE: 表示不缓存任何内容。
//DiskCacheStrategy.SOURCE: 表示只缓存原始图片。
//DiskCacheStrategy.RESULT: 表示只缓存转换过后的图片(默认选项)。
//DiskCacheStrategy.ALL : 表示既缓存原始图片,也缓存转换过后的图片。
AFL——Android框架学习