Android 大图显示优化方案-加载Gif 自定义解码器

基于Glide做了图片显示的优化,尤其是加载Gif图的优化,原生Glide加载Gif图性能较低。在原生基础上做了自定义解码器的优化,提升Glide性能

Glide加载大图和Gif 尤其是列表存在gif时,会有明显卡顿,cpu和内存占用较高,
Glide的优势 就是有一套图片生命周期的维护,但是加载gif效率比不上android-gif-drawable库,原因就是glide是java层加载的,后者是native层加载的 使用的是giflib库

解决方案:
Glide+giflib

因为giflib是C库,我们调用比较不便,好在Google官方封装好了一个 frameSequence
 


步骤一:生成so文件

下载好framesequence和giflib包,然后在framesequence目录中创建external目录,并将giflib解码目录复制到该目录下,然后执行ndk-build,最后将生成的so放到jnilibs目录下。 

 

步骤二:创建FrameSequence对象以及FrameSequenceDrawable对象

frameSequence的sample项目中已有了,直接复制过来就可以使用了

步骤三 自定义glide资源解码器

经过以上三步,准备工作已做好,接下来就是要将frameSequence和glide进行结合了。frameSequence负责图片解码,glide负责下载和生命周期维护。想要替换解码部分,就必须了解glide的实现了。glide加载过程分为加载和解码两大步骤,其中加载过程是通过模型加载器(ModelLoader)来实现,而解码过程是通过资源解码器(ResourceDecoder)来实现的,所以我们要做的就是将glide的ResourceDecoder中默认的解码操作替换成frameSequence。

那应该怎么给glide注册一个资源解码器呢?

其实Glide v4 使用 APT(注解处理器) 来生成出一个 API。可以为 Generated API 扩展自定义选项,我们可以继承AppGlideModule,重写registerComponents方法,在里面添加一个gif解码器。注意需要使用@GlideModule进行注解,添加完该注解后在编译时会自动生成一些类。这里将glide.getBitmapPool传递到解码器中是为了bitmap的复用

写好这个类后,我们直接编译一下项目,就会发现glide自动为我们生成了很多的java文件,如下图:

接下来我们再看看核心的解码器需要做什么操作

我们可以看到,这里面首先构造方法接收到了glide注册机传过来的bitmapPool,用在decode方法中进行复用。在handles中返回true代表我们的解码器直接处理了该任务,然后在最核心的decode方法中,我们初始化了一个FrameSequenceDrawable并且返回。这里由于返回值是Resource,所以我们不得不包了一层自定义的Resource子类。

什么是内存抖动?

内存抖动是指频繁的申请内存,然后又回收内存,使得内存使用很不稳定,万一没有回收好就会产生内存泄漏。

什么是内存碎片?

在连续的内存空间中,有一部分内存被使用,另一部分已经被回收,所以导致目前可使用的内存空间不是连续的,而不是连续的将不可以同时一次性拿来使用。比如内存空间是1 2 3 4个格子,其中1和3是正在使用的内存,2和4是空闲内存,此时如果2和4单个的内存空间不够,那么就需要同时申请到2和4,由于2和4的空间不连续,所以就会导致申请失败。其中2和4这2个内存空间就被称为内存碎片,太小的碎片将无法使用,非常影响效率。

有关bitmapPool的复用

这里我贴出谷歌官方的2张图,第一张是复用前,每个图片都分配一个内存空间。第二张是复用后,所有图片复用同一个bitmap空间,减少内存使用。

步骤四 自定义解码器的使用

最后,我们通过调用之前通过APT生成的GlideApp,然后通过as方法传入FSDrawable的方式来调用我们自定义的解码器

是否还能优化一下调用流程?

以上实际的加载优化已经完成,但是我们发现调用的时候需要as方法传入FrameSequenceDrawable,写起来很不方便,希望能改成类似于asgif这种调用方法,这个又需要使用到glide自带的APT技术了,换句话说我们需要使用一个注解。这里我们新建一个类,类名随意,然后使用一下@GlideExtension注解,这里需要注意的是,类中必须要有一个私有无参构造方法,不然glide是会报错的。然后我们自定义一个asGif2方法,使用@GlideType进行标注,在里面就调用requestBuilder.apply方法就好了。写完以后要编译一下,让glide通过注解生成该方法,这样就可以直接调用了。

总结:glide优化其实就是指利用glide可以自定义解码器的特点,我们自己来定义并且注册了一个资源解码器,其中指定使用FrameSequence来进行解码,核心其实就是使用的giflib库。利用native层来实现资源的解码,提升了加载效率,其中我们还特意对bitmap进行了复用。然后为了调用方便,我们将调用方式从as改为asGif2,调用更加清晰明了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/127436.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【RabbitMQ】介绍及消息收发流程

介绍 RabbitMQ 是实现 AMQP(高级消息队列协议)的消息中间件的一种,最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。 RabbitMQ 主要是为了实现系统之间的双向解耦而实…

LeetCode 138. Copy List with Random Pointer【链表,DFS,迭代,哈希表】中等

本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章…

CSS笔记(黑马程序员pink老师前端)圆角边框

圆角边框 border-radius:length; 效果显示 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Documen…

[杂谈]-2023年实现M2M的技术有哪些?

2023年实现M2M的技术有哪些&#xff1f; 文章目录 2023年实现M2M的技术有哪些&#xff1f;1、寻找连接2、M2M与IoT3、流行的 M2M 协议 在当今的数字世界中&#xff0c;机器对机器 (M2M) 正在迅速成为标准。 M2M 包括使联网设备能够交换数据或信息的任何技术。 它可以是有线或无…

springboot整合elasticsearch使用案例

引入依赖 <dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId> </dependency> 添加注入 import org.apache.http.HttpHost; import org.elasticsearch.client.Res…

项目(智慧教室)第四部分,页面交互功能,WebServer建立与使用,

一。页面构思 1.标题栏 大标题&#xff1a;智慧教室管理系统 小标题&#xff1a;灯光&#xff0c;报警&#xff0c;风扇&#xff0c;温度&#xff0c;湿度&#xff0c;光照 2.样式设计 背景设置。字体设置&#xff08;字体大小&#xff0c;格式&#xff0c;颜色&#xff09; 3.…

【人月神话】深入了解软件工程和项目管理

文章目录 &#x1f468;‍⚖️《人月神话》的主要观点&#x1f468;‍&#x1f3eb;《人月神话》的主要内容&#x1f468;‍&#x1f4bb;作者介绍 &#x1f338;&#x1f338;&#x1f338;&#x1f337;&#x1f337;&#x1f337;&#x1f490;&#x1f490;&#x1f490;&a…

oracle将一个用户的表复制到另一个用户

注&#xff1a;scott用户和scott用户下的源表&#xff08;EMP&#xff09;本身就有&#xff0c;无需另行创建。 GRANT SELECT ON SCOTT.emp TO BI_ODSCREATE TABLE ODS_EMP AS SELECT * FROM SCOTT.emphttp://www.bxcqd.com/news/77615.html SQL语句查询要修改密码的用户…

通过Siri打造智能爬虫助手:捕获与解析结构化数据

在信息时代&#xff0c;我们经常需要从互联网上获取大量的结构化数据。然而&#xff0c;传统的网络爬虫往往需要编写复杂代码和规则来实现数据采集和解析。如今&#xff0c;在苹果公司提供的语音助手Siri中有一个强大功能可以帮助我们轻松完成这项任务——通过使用自定义指令、…

OpenCV 05(图像的算术与位运算)

一、图像的算术运算 1.1 图像的加法运算 - add opencv使用add来执行图像的加法运算 图片就是矩阵, 图片的加法运算就是矩阵的加法运算, 这就要求加法运算的两张图shape必须是相同的. import cv2 import numpy as npcat cv2.imread(D:\\3-project\\zyj\\pythonCNN\\pic\\c…

libbpf-bootstrap安卓aarch64适配交叉编译

1.为什么移植 疑惑 起初我也认为&#xff0c;像libbpf-bootstrap这样在ebpf程序开发中很常用的框架&#xff0c;理应支持不同架构的交叉编译。尤其是向内核态的ebpf程序本身就是直接通过clang的-target btf直接生成字节码&#xff0c;各个内核上的ebpf虚拟机大同小异&#xf…

音频——I2S DSP 模式(五)

I2S 基本概念飞利浦(I2S)标准模式左(MSB)对齐标准模式右(LSB)对齐标准模式DSP 模式TDM 模式 文章目录 DSP formatDSP A时序图逻辑分析仪抓包 DSP B时序图逻辑分析仪抓包 DSP format DSP/PCMmode 分为 Mode-A 和 Mode-B 共 2 种模式。不同芯⽚有的称为 PCM mode 有的称为 DSP m…

UG二次开发 向量叉乘 UF_VEC3_cross

文章作者:里海 来源网站:王牌飞行员_里海_里海NX二次开发3000例,里海BlockUI专栏,C\C++-CSDN博客 简介: UG二次开发 向量叉乘 UF_VEC3_cross,xyz三个向量已知2个求另外1个。 效果: 代码: #include "me.hpp"void ufusr(char* param, int* retcode, int paramLe…

数据结构与算法学习(day4)——解决实际问题

前言 在本章的学习此前&#xff0c;需要复习前三章的内容&#xff0c;每个算法都动手敲一遍解题。宁愿学慢一点&#xff0c;也要对每个算法掌握基本的理解&#xff01; 前面我们学习了简化版桶排序、冒泡排序和快速排序三种算法&#xff0c;今天我们来实践一下前面的三种算法。…

C# OpenVinoSharp PP-TinyPose 人体姿态识别

效果 项目 部分代码 using OpenCvSharp; using OpenCvSharp.Extensions; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms;name…

机器学习——支持向量机(SVM)

机器学习——支持向量机&#xff08;SVM&#xff09; 文章目录 前言一、SVM算法原理1.1. SVM介绍1.2. 核函数&#xff08;Kernel&#xff09;介绍1.3. 算法和核函数的选择1.4. 算法步骤1.5. 分类和回归的选择 二、代码实现&#xff08;SVM&#xff09;1. SVR&#xff08;回归&a…

【矩阵分解】PCA - 主成分分析中的数学原理

前言 本文主要对PCA主成分分析中的数学原理进行介绍&#xff0c;将不涉及或很少涉及代码实现或应用&#xff0c;阅读前请确保已了解基本的机器学习相关知识。 文章概述 PCA主成分分析属于矩阵分解算法中的入门算法&#xff0c;通过分解特征矩阵来实现降维。 本文主要内容&a…

硬件学习件Cadence day13 PCB设计中一些设置, 铜皮到钻孔的距离设置, 差分线的设置,板层信息表

1. 设置铺铜中铜皮到钻口&#xff0c;连线的距离。 1. 打开设置界面 2. 设计界面 调整到 铜皮设置界面 2. 高速线的设置 &#xff08;差分对传输线的设置&#xff09; 1. 打开设置界面 2. 来到 差分线设置界面 3. 把界面往右看&#xff0c; 设置差分线的之间距离&#xff0c;…

(二十四)大数据实战——Flume数据流监控之Ganglia的安装与部署

前言 本节内容我们主要介绍一下Flume数据流的监控工具Ganglia。Ganglia是一个开源的分布式系统性能监控工具。它被设计用于监视大规模的计算机群集&#xff08;包括集群、网格和云环境&#xff09;&#xff0c;以便收集和展示系统和应用程序的性能数据。Ganglia 可以轻松地扩展…

【多线程】线程安全 问题

线程安全 问题 一. 线程不安全的典型例子二. 线程安全的概念三. 线程不安全的原因1. 线程调度的抢占式执行2. 修改共享数据3. 原子性4. 内存可见性5. 指令重排序 一. 线程不安全的典型例子 class ThreadDemo {static class Counter {public int count 0;void increase() {cou…