glide4.11.0封装gfilib优化gif图片加载

2023-05-16

文章目录

    • 具体步骤 :
      • 下载giflib 和 framesequence
      • 导入并集成 giflib 和 framesequence
      • glide的配置gif使用giflib集成
      • 开始使用
      • 加载思路
        • 创建自定义GifDrawable

需求: 目前项目中加载进度框采用的是一个gif图片, 使用图片加载框架为glide.

Glide 是如何加载 GIF 动图的?

首先需要区分加载的图片类型,即网络请求拿到输入流后,获取输入流的前三个字节,若为 GIF 文件头,则返回图片类型为 GIF。

确认为 GIF 动图后,会构建一个 GIF 的解码器(StandardGifDecoder),它可以从 GIF 动图中读取每一帧的数据并转换成 Bitmap,然后使用 Canvas 将 Bitmap 绘制到 ImageView 上,下一帧则利用 Handler 发送一个延迟消息实现连续播放,所有 Bitmap 绘制完成后又会重新循环,所以就实现了加载 GIF 动图的效果。

未使用gifli加载gif图,使用glide加载gif效果:

  • 内存消耗: 80.7

使用giflib加载gif图效果:

  • 内存消耗: 40.9

解决方案 : 使用 giflib 库 (gif编解码库c++ ),并提供Java 。使用它要比glide加载GIF效果效果要好,glide加载加载GIF图片CPU占用高,并且内存占用一直在增加。采用JNI调用的方式加载gif图.

具体步骤 :

下载giflib 和 framesequence

  1. giflib 下载 framesequence其jin依赖于giflib,所以,得下载其源码,地址在 https://android.googlesource.com/platform/external/giflib/+/refs/heads/master 可以看到giflib已经集成到Android源码里面了

或者在这里下载 https://android.googlesource.com/platform/external/giflib/+/android-9.0.0_r16

  1. framesequence 下载 framesequence是Androidframework中ex里的一个工具包,其源码地址在
    https://android.googlesource.com/platform/frameworks/ex/+/android-9.0.0_r16/framesequence/

导入并集成 giflib 和 framesequence

首先把项目转化为c++项目. 然后在cpp目录创建giflib文件夹,将下载的giflib源码拷贝到giflib文件夹下面

如下图:

将无用的文件删除后在使用cmakelist编译

cmake_minimum_required(VERSION 3.4.1)

#引入源码
file(GLOB_RECURSE GIF_LIB ${CMAKE_SOURCE_DIR}/giflib/*.*)
file(GLOB_RECURSE FRAME_SEQUENCE ${CMAKE_SOURCE_DIR}/*.cpp*)

add_library(mygif
        SHARED
        ${FRAME_SEQUENCE}
        ${GIF_LIB})

list(APPEND LIBS
        jnigraphics
        android
        GLESv2
        log
        )

set(LIBS)
list(APPEND LIBS
        jnigraphics
        android
        GLESv2
        log
        )

target_link_libraries(mygif ${LIBS})

glide的配置gif使用giflib集成

GifDecoder

package com.example.giflibdemo;

import android.graphics.Bitmap;
import android.support.rastermill.FrameSequence;
import android.support.rastermill.FrameSequenceDrawable;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.bumptech.glide.load.Options;
import com.bumptech.glide.load.ResourceDecoder;
import com.bumptech.glide.load.engine.Resource;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;

import java.io.IOException;
import java.io.InputStream;

public class GifDecoder implements ResourceDecoder<InputStream, FrameSequenceDrawable> {

    private BitmapPool bitmapPool;

    public GifDecoder(BitmapPool bitmapPool) {
        this.bitmapPool = bitmapPool;
    }

    @Override
    public boolean handles(@NonNull InputStream source, @NonNull Options options) throws IOException {
        return true;
    }

    @Nullable
    @Override
    public Resource<FrameSequenceDrawable> decode(@NonNull InputStream source, int width, final int height, @NonNull Options options) throws IOException {
        FrameSequence frameSequence = FrameSequence.decodeStream(source);
        FrameSequenceDrawable frameSequenceDrawable = new FrameSequenceDrawable(frameSequence, new FrameSequenceDrawable.BitmapProvider() {
            @Override
            public Bitmap acquireBitmap(int minWidth, int minHeight) {
                return bitmapPool.get(minWidth, minHeight, Bitmap.Config.ARGB_8888);
            }

            @Override
            public void releaseBitmap(Bitmap bitmap) {
                bitmapPool.put(bitmap);
            }
        });
        return new GifResource(frameSequenceDrawable);
    }
}

GifGlideModule

package com.example.giflibdemo;

import android.content.Context;
import android.support.rastermill.FrameSequenceDrawable;

import androidx.annotation.NonNull;

import com.bumptech.glide.Glide;
import com.bumptech.glide.GlideBuilder;
import com.bumptech.glide.Registry;
import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.module.AppGlideModule;
import com.bumptech.glide.module.LibraryGlideModule;

import java.io.InputStream;

@GlideModule
public class GifGlideModule extends AppGlideModule {
//public class GifGlideModule extends LibraryGlideModule {


    @Override
    public void applyOptions(@NonNull  Context context, @NonNull  GlideBuilder builder) {
        super.applyOptions(context, builder);
    }

    @Override
    public void registerComponents(@NonNull Context context,
                                   @NonNull Glide glide, @NonNull Registry registry) {
        super.registerComponents(context, glide, registry);
        registry.append(Registry.BUCKET_GIF, InputStream.class,
                FrameSequenceDrawable.class, new GifDecoder(glide.getBitmapPool()));
//        registry.append(Registry.BUCKET_GIF, InputStream.class,
//                FrameSequenceDrawable.class, new GifDecoder(glide.getBitmapPool()));
    }

    @Override
    public boolean isManifestParsingEnabled() {
        return false;
    }
}

GifResource

package com.example.giflibdemo;

import android.support.rastermill.FrameSequenceDrawable;

import androidx.annotation.NonNull;

import com.bumptech.glide.load.resource.drawable.DrawableResource;


public class GifResource extends DrawableResource<FrameSequenceDrawable> {

    public GifResource(FrameSequenceDrawable drawable) {
        super(drawable);
    }

    @NonNull
    @Override
    public Class<FrameSequenceDrawable> getResourceClass() {
        return FrameSequenceDrawable.class;
    }

    @Override
    public int getSize() {
        return 0;
    }

    @Override
    public void recycle() {
        drawable.stop();
        drawable.destroy();
    }
}

GlideExtension

package com.example.giflibdemo;

import android.support.rastermill.FrameSequenceDrawable;

import com.bumptech.glide.RequestBuilder;
import com.bumptech.glide.annotation.GlideType;
import com.bumptech.glide.request.RequestOptions;

@com.bumptech.glide.annotation.GlideExtension
public class GlideExtension {

    private GlideExtension() {

    }

    final static RequestOptions DECODE_TYPE = RequestOptions
            .decodeTypeOf(FrameSequenceDrawable.class)
            .lock();

    @GlideType(FrameSequenceDrawable.class)
    public static RequestBuilder<android.support.rastermill.FrameSequenceDrawable> asGif2(RequestBuilder<FrameSequenceDrawable> requestBuilder) {
//        RequestBuilder<android.support.rastermill.FrameSequenceDrawable
        return requestBuilder.apply(DECODE_TYPE);

    }

}

开始使用


        int gif = R.mipmap.loading_gif;
        //String gif = "http://2zhoumu-comic-public-test.oss-cn-hangzhou.aliyuncs.com/cover/comic/gc1100004.gif";
        //使用giflib加载
        GlideApp.with(this).as(FrameSequenceDrawable.class).load(gif).into(imageView);
        //使用glide原生加载
//        Glide.with(this).asGif().load(gif).into(imageView);

加载思路

考虑如何使用,一般是给ImageView设置bitmap,但是bitmap存储效率低.故而使用Drawable. ImageView有一个setImageDrawable的方法

思路:

  1. 先将gif解压成为一帧一帧的数据
  2. 将数据绘制到drawable上面去
  3. 最后将drawable设置到ImagView上面去

系统有个BitmapDrawable,但是这里需要自己定义一个GifDrawable用于显示gif图片 这里framesequence 已经帮我们做了.

创建自定义GifDrawable

GifDrawable 需要做的操作:

  1. 首先Java准备一个Bitmap Bitmap是要Java端初始化出来的 传给C++
  2. gif 解压出来之后每一帧(Screen) 填充 成Bitmap
  3. 把Bitmap 绘制到Canvas 利用 canvas.drawBitmap

注意点:
需要让jni创建java对象


glide 使用glidemodule 官方文档

https://bumptech.github.io/glide/doc/configuration.html


其他资料

Bitmap - 称作位图,一般位图的文件格式后缀为bmp,当然编码器也有很多如RGB565、RGB888。作为一种逐像素的显示对象执行效率高,但是缺点也很明显存储效率低。我们理解为一种

存储对象比较好。
Drawable - 作为Android平下通用的图形对象,它可以装载常用格式的图像,比如GIF、PNG、JPG,当然也支持BMP,当然还提供一些高级的可视化对象,比如渐变、图形等。

giflib api 加载方式:

  1. 一次性读取gif的信息,然后加载
  2. 使用流的方式读取,自己去解析加载
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

glide4.11.0封装gfilib优化gif图片加载 的相关文章

  • 手把手教你无线数传电台透明传输的配置全攻略

    透明传输 功能说明 任意电台发送数据 xff0c 具有相同地址且相同信道的电台均可同时接收数据 数据以透明方式发送和接收 xff0c 所发即所收 电台设置 1 需将 OPTION 特殊功能寄存器的第 7 位配置成 0 xff0c 透明传输模
  • unity寻路插件(A* Pathfinding)小结

    A Pathfinding 详细使用教程 基本功能 1 astarpath cs 核心组件 xff0c 相当于 路 xff0c 场景里应该只存在一个 2 Seeker cs 相当于一个代理 xff0c 寻找路径 xff0c 需要绑定在每一个
  • Socket网络通信C++编程总结

    概述 Socket编程有三种 xff0c 流式套接字 xff08 SOCK STREAM xff09 数据报套接字 SOCK DGRAM 原始套接字 SOCK RAW 前两者较常用 xff0c 这里简单总结前两种编程步骤以及一些参考资料 编
  • 【STM32+cubemx】0029 HAL库开发:HMC5883L磁力计的应用(电子指南针)

    今天我们来学习电子磁力计HMC5883L的使用 先介绍磁力计的基础知识 xff0c 再给一个获取磁力计数据的例子 xff0c 最后讲解HMC5883L磁力计的校准 xff0c 以及一些使用中的经验 1 xff09 HMC5883L磁力计的基
  • stm32F103R6之BKP(备份寄存器)

    目录 概述 侵入检测 RTC校准 概述 Stm32F103有42个16位的备份寄存器 他们处在备份域里 xff0c 当VDD电源被切断 xff0c 他们仍然由VBAT维持供电 当系统在待机模式下被唤醒 xff0c 或系统复位或电源复位时 x
  • Stm32F103R6之控制器局域网

    目录 概述 双CAN bxCAN工作模式 CAN协议特点 xff1a ISO11898标准CAN物理特性 CAN协议帧 概述 bxCAN是基本扩展CAN Basic Extended CAN 的缩写 xff0c 它支持CAN协议2 0A和2
  • 如何输出一个数的二进制数

    实现思想 xff1a 二进制数是以bit为操作数 xff0c 所以要想将一个数转换为二进制数 xff0c 我们需要先要将输入的数字转化为二进制数 xff0c 然后从高位到低位判断每一位是 1 还是 0 xff0c 最后把对应的 1 和 0
  • 使用libcurl库编写HTTP客户端(包括GET/POST/HTTPS)

    最近在写一个应用程序 需要与HTTP服务器进行数据交互 于是乎自己写了一个类似wget的功能的客户端 实现很简单 但是功能不给力 只可基本功能 于是又在网上找了找 发现使用libcurl库很方便 很强大 比起wget之类的 强大不是一点点
  • 修改系统默认shell为bash

    xfeff xfeff 从 ubuntu 6 10 开始 xff0c ubuntu 就将先前默认的bash shell 更换成了dash shell xff1b 其表现为 bin sh 链接倒了 bin dash而不是传统的 bin bas
  • 如何解决Reporting Services目录数据库文件存在的问题

    出处 xff1a http blog sina com cn s blog 6bace3cc0101jlxv html 错误提示 xff1a 自检时提示 Reporting Services目录数据库文件存在 失败 xff0c Report
  • 无线射频专题《射频合规,2.4GHz WIFI测试指标详解》

    目录 引言 Transmitter Power 发送功率 Transmit Spectrum Mask 发送信号频谱模版 Frequency Error 频率误差 EVM 矢量误差幅度 Band Edges and harmonics 频带
  • 获取当前访问的路径

    String returl 61 request getRequestURL 43 request getQueryString 61 61 null 34 34 34 34 43 request getQueryString
  • 抓取百度关键词排名

    最近在做百度关键词排名的功能 xff0c 发现网上资源比较少 xff0c 于是自己琢磨了一下 xff0c 写一下笔记 xff1b 本文重点在于提供思路 xff0c 请不要过分依赖 xff0c 本文主要靠抓取页面标签来完成 xff0c 如果百
  • 抓取百度关键词排名、标题、连接、描述

    抓取百度关键词排名 标题 连接 描述 转载请标明出处 最近在做百度关键词排名的功能 xff0c 发现网上资源比较这里写代码片少 xff0c 于是自己琢磨了一下 xff0c 写一下笔记 xff1b 本文重点在于提供思路 xff0c 请不要过分
  • Windows Server 2008远程桌面端口的修改

    Windows Server 2008远程桌面端口系统默认的是3389端口 xff0c 但出于安全考虑 xff08 谁都不希望任何都可以远程连接到自己的服务器吧 xff0c 哈哈 xff09 xff0c 经常我们把系统默认的3389端口更改
  • jsp 登陆成功后,显示登录的用户名

    首先在登陆界面将用户名保存起来 xff0c 我这里是将用户名提交到Servlet然后再进行保存 xff0c 从登录界面取用户参数 String uname 61 request getParameter 34 userName 34 req
  • 背景图片随网页的变化而变化(指大小)

    lt DOCTYPE HTML PUBLIC 34 W3C DTD HTML 4 01 Transitional EN 34 gt lt html xmlns 61 34 http www w3 org 1999 xhtml 34 gt l
  • 为什么vscode用久了电脑速度变慢?

    1 vscode 插件占用的内存 1 已经安装的插件 2 插件占用内存 我可以看到 xff0c vs code 这个程序下面有多个进程在跑 xff0c 插件占用的内存比我电脑剩下所有占用的内存还要高 xff0c 但是vs code 性能还是
  • ROS基础学习(一)---创建工作空间

    工作空间 xff08 workspace xff1a 是一个存放工程开发相关文件的文件夹 src xff1a 代码空间 xff08 Source Space build 编译空间 xff08 Build Space devel 开发空间 x
  • 一个简单的爬虫程序,爬取网站的图片

    最简单的爬虫是分析网页 xff0c 如果要爬取图片 xff0c 就要将图片在网页中的格式进行分析 xff0c 取到图片的连接 xff0c 接着下载图片 xff1b 由于网页中还会链接到其他的网页 xff0c 所以需要将其中的所有网页取出 x

随机推荐

  • python文件操作及引申的代码行数统计

    文件操作一般包括文件的读写 xff0c 文件夹的创建 xff0c 文件夹的删除等 第一部分 xff1a python文件读写的基本操作 python打开文件一般使用 open函数 xff1a open file mode 61 39 r 3
  • 超声波测距仪

    基本原理 超声波是利用反射的原理测量距离的 xff0c 被测距离一端为超声波传感器 xff0c 另一端必须有能反射超声波的物体 测量距离时 xff0c 将超声波传感器对准反射物发射超声波 xff0c 并开始计时 xff0c 超声波在空气中传
  • Authorization 值中Bearer空格加token值在python接口请求中如何实现

    在项目中每个接口请求都需要Authorization 值 xff0c 而Authorization他的值必须 Bearer 加token值 xff0c 刚开始自己忘记添加Bearer 接口请求一直拒绝访问 xff0c 后来用fiddler抓
  • printf格式化字符串漏洞原理解析

    读任意地址 printf 34 x 34 只给格式化字符串 xff0c 而不给参数 xff0c 会导致内存泄漏从而读到内存中其他地址的数据 N x参数可以以16进制方式打印第N个参数的内容 xff0c 通过修改N xff0c 我们可以遍历栈
  • 教程丨利用微软官方工具制作U盘安装Win10系统

    一 制作Win10安装U盘 1 登录网站 https www microsoft com zh cn software download windows10 下载 MediaCreationTool 工具 xff0c 这里我们直接点击 立即
  • Linux常用命令大全

    发布jar包 nohup java jar xxxx jar gt dev null 2 gt amp 1 amp 修改nginx conf 后刷新配置 usr local nginx sbin nginx t 测试配置文件修改是否正常 u
  • Zab协议详解

    什么是Zab协议 xff1f Zab协议 的全称是 Zookeeper Atomic Broadcast xff08 Zookeeper原子广播 xff09 Zookeeper 是通过 Zab 协议来保证分布式事务的最终一致性 Zab协议是
  • 谷歌浏览器安装json格式化插件

    实际开发工作中经常用到json数据 xff0c 那么就会有这样一个需求 xff1a 在谷歌浏览器中访问URL地址返回的json数据能否按照json格式展现出来 比如 xff0c 在谷歌浏览器中访问 xff1a http jsonview c
  • Seata详解(一)

    分布式事务 事务是数据库的概念 xff0c 数据库事务 xff08 ACID xff1a 原子性 一致性 隔离性和持久性 xff09 xff1b 分布式事务的产生 xff0c 是由于数据库的拆分和分布式架构 微服务 带来的 xff0c 在常
  • RocketMQ的事务消息和改造

    什么是 rmq分布式事务消息 xff1f Apache RocketMQ在4 3 0版中已经支持分布式事务消息 xff0c 这里RocketMQ采用了2PC的思想来实现了提交事务消息 xff0c 同时增加一个补偿逻辑来处理二阶段超时或者失败
  • session和token区别

    一 session的状态保持及弊端 xff08 1 xff09 当用户第1次通过浏览器使用用户名和密码访问服务器时 xff0c 服务器对用户名和密码进行验证 xff08 2 xff09 验证成功后 xff0c 在服务器端生成并保存sessi
  • 关于阿里云对RocketMQ的topic,tag,consumer关系的理解

    什么是订阅关系一致 消息队列RocketMQ版 阿里云帮助中心 RocketMQ 中Topic Tag GroupName基本概念介绍 Young丶的博客 CSDN博客 rocketmq topic和group的区别 转载
  • MySql Workbench 8.0汉化插件分享

    打开workbench的安装数据目录 xff0c 路径是 xff1a C Program Files MySQL MySQL Workbench 8 0 CE data 打开以后 xff0c 可以看到下面有一堆的xml结尾的文件 xff0c
  • Java-Jdk12版本下载后没有Jre的解决方案以及配置环境变量

    新本Jdk12版本下载后不像以前的版本会自动生成Jre文件夹 xff0c 通过dos命令行可以解决 1 下载jdk12 网址 xff1a https www oracle com technetwork java javase downlo
  • android--性能优化1--首屏优化&启动速度与执行效率检测

    文章目录 实战篇traceview 工具使用操作步骤操作步骤2 systrace 工具使用操作步骤 AOP 工具 hugo 的使用使用方法效果 BlockCanary 使用AOP 工具使用 AspectJ操作步骤 优化方案 异步线程优化 针
  • error Failed connect to github.com 443原因 Github更换认证方式

    Github更换认证方式 github近期调整了认证方式 xff0c 不再允许第三方工具基于账号密码来访问和管理项目了 除非使用github DeskTop 自带的客户端 好坑啊 我一直再用android studio 自带的提交工具很方便
  • AppCompatRatingBar备份用 下次拷贝直接用自定义图片背景

    控件 lt androidx appcompat widget AppCompatRatingBar android id 61 34 64 43 id rating bar 34 style 61 34 64 style myRating
  • 备份Edittext编辑框字数限制ui以及逻辑

    ui布局 etContent addTextChangedListener new TextWatcher 记录输入的字数 private CharSequence enterWords private int selectionStart
  • android—性能优化2—内存优化

    文章目录 性能优化 工具 memory profilerLeakCanaryarthookepic 库 java内存管理机制java 内存回收机制Android内存管理机制Dalvik与 Art区别Low Memory Killer 内存抖
  • glide4.11.0封装gfilib优化gif图片加载

    文章目录 具体步骤 下载giflib 和 framesequence导入并集成 giflib 和 framesequenceglide的配置gif使用giflib集成开始使用加载思路创建自定义GifDrawable 需求 目前项目中加载进度