每天学习一个Android中的常用框架——10.Glide

1. 简介

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的学习吧。

2. 特性

根据官方文档的说明,Glide的特性可以分由三个方面进行讲解:

  • API
    Glide 使用简明的流式语法API,这是一个非常棒的设计,因为它允许你在大部分情况下一行代码搞定需求:

    Glide.with(fragment)
    .load(url)
    .into(imageView);
    

    这句描述确实不夸张,因为Glide的大部分业务基本上都是倚靠这行代码就可以实现

  • 性能
    Glide 充分考虑了Android图片加载性能的两个关键方面:

    • 图片解码速度
    • 解码图片带来的资源压力

    为了让用户拥有良好的App使用体验,图片不仅要快速加载,而且还不能因为过多的主线程I/O或频繁的垃圾回收导致页面的闪烁和抖动现象。

  • 步骤
    Glide使用了多个步骤来确保在Android上加载图片尽可能的快速和平滑:

    • 自动、智能地下采样(downsampling)和缓存(caching),以最小化存储开销和解码次数;
    • 积极的资源重用,例如字节数组和Bitmap,以最小化昂贵的垃圾回收和堆碎片影响;
    • 深度的生命周期集成,以确保仅优先处理活跃的Fragment和Activity的请求,并有利于应用在必要时释放资源以避免在后台时被杀掉。

正因为Glide具有这三方面的优点,于是成为了当下主流的图片加载框架。说实话,它的使用确实相当简单。在接下来的演示环节中,读者就可以感受到。

3. 演示

3.1 集成

在使用框架之前,第一步永远都是集成。我们去Glide的GitHub官网上搜索最新版本:Glide,然后修改module下的build.gradle,代码如下:

    implementation 'com.github.bumptech.glide:glide:4.11.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'

3.2 配置

在使用Glide的时候,我们可能需要申请一些权限。修改Manifest.xml,添加相应权限,代码如下:

	<uses-permission android:name="android.permission.INTERNET"/>
    <!--
    Allows Glide to monitor connectivity status and restart failed requests if users go from a
    a disconnected to a connected network state.
    -->
    <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" />

3.2 基本功能

这里为了演示Glide提供的最基本的图片加载功能,就使用尽可能简单的业务逻辑。修改activity_main.xml,增加一个ImageView控件和两个按钮,按钮分别作用与让图片的显示和图片的清除,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<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的一些拓展功能。当然,限于篇幅限制,接下来就只贴出业务逻辑代码和一些简单的说明,就不一一详解了。

3.3 拓展功能

3.3.1 四种形式的图片加载

// 加载本地图片
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);

3.3.2 带有占位图的图片加载

占位图,目的是为在图片还未加载出来的时候,提前展示给用户的一张图片;

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 : 表示既缓存原始图片,也缓存转换过后的图片。

3.3.3 静态图片的图片加载

Glide.with(this)
     .load(url)
     .asBitmap()//只加载静态图片,如果是git图片则只加载第一帧。
     .placeholder(R.drawable.loading)
     .error(R.drawable.error)
     .diskCacheStrategy(DiskCacheStrategy.NONE)
     .into(imageView);

3.3.4 动态图片的图片加载

Glide.with(this)
     .load(url)
     .asGif()//加载动态图片,若现有图片为非gif图片,则直接加载错误占位图。
     .placeholder(R.drawable.loading)
     .error(R.drawable.error)
     .diskCacheStrategy(DiskCacheStrategy.NONE)
     .into(imageView);

3.3.5 指定大小图片的图片加载

Glide.with(this)
     .load(url)
     .placeholder(R.drawable.loading)
     .error(R.drawable.error)
     .diskCacheStrategy(DiskCacheStrategy.NONE)
     .override(100, 100)//指定图片大小
     .into(imageView);

3.3.6 不带缓存的图片加载

这里的不带缓存分为两种情况,即:

  • 不带内存缓存

    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 : 表示既缓存原始图片,也缓存转换过后的图片。
    

4. 源码地址

AFL——Android框架学习

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赈川

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值