android pdf框架-8,图片缓存
解码会产生很多图片,滑过后不要显示,如果直接回收,会浪费不少资源.
在没有缓存的情况下,会看到gc还是比较频繁的.
有了缓存后,明显gc少了.
目录
常用的缓存
自定义缓存
显示相关的内存缓存
解码缓存池
内存缓存实现:
解码缓存池实现:
常用的缓存
lrucache,这是最常用的,也是android sdk里面有的.就是按访问时间顺序,内部使用linkedhashmap,会记录访问时间.
androidx.core.util.Pools
这是一个接口,实现后可以自己管理池.严格来说,它并不是一个缓存类,是用来构建缓存的基础类.
用lrucache作缓存,有一些不好的点,设置了容量并不是图片的字节总数,是图片的张数.这对于图片大小不一的情况,可能并不是很好.
自定义缓存
显示相关的内存缓存
需要string作缓存key,能读取,且能根据容量把最早未访问的清除出缓存队列.
解码缓存池
当需要解码时,从池里面找到bitmap,对于高版本的系统,解码可以使用比当前高宽大的图片来处理.那么当图片从上面的内存缓存中清除,不是调用recycle(),而是将它放入解码缓存池.这对于解码来说,会明显减少gc.
内存缓存实现:
既然lru这么好用,就参与它,把源码拿来修改下.有了自动清除最早访问的位图功能,又有根据总字节数去管理缓存.
private static final int mMaxPoolSizeInBytes = 100 * 1024 * 1024;private int mPoolSizeInBytes = 0;
定义了最大缓存100m, 这个值可以根据系统内存大小去调整,这里先固定.
private final LinkedHashMap<String, Bitmap> map = new LinkedHashMap<>(16, 0.75f, true);
默认先设16
获取图片,不需要去创建,如果为空就返回空.这与lru不一样的.
public final Bitmap getBitmap(@NonNull String key) {if (key == null) {throw new NullPointerException("key == null");}Bitmap mapValue;synchronized (this) {mapValue = map.get(key);if (mapValue != null) {hitCount++;return mapValue;}missCount++;}return null;}//添加图片,
public final Bitmap addBitmap(@NonNull String key, @NonNull Bitmap value) {if (key == null || value == null) {throw new NullPointerException("key == null || value == null");}
//添加前先判断是否总容量已经达到限定的值,如果是就清除,直到总容量符合要求,然后再添加.如果总容量设置很小,那么这里的效率会比较低.while (mPoolSizeInBytes > mMaxPoolSizeInBytes) {removeLast();}mPoolSizeInBytes += value.getByteCount();Bitmap previous;synchronized (this) {putCount++;previous = map.put(key, value);if (previous != null) { //对于移除的要把容量减去它的大小.mPoolSizeInBytes -= previous.getByteCount();}}//System.out.println(String.format("put.size:%s, key:%s, val:%s, size:%s", map.size(), key, value, mPoolSizeInBytes));if (previous != null) {entryRemoved(false, key, previous, value);}return previous;}//与lrucache差不多,记得容量的计算
private void removeLast() {String key;Bitmap value;synchronized (this) {if (map.isEmpty()) {return;}Map.Entry<String, Bitmap> toEvict = map.entrySet().iterator().next();key = toEvict.getKey();value = toEvict.getValue();map.remove(key);mPoolSizeInBytes -= value.getByteCount();evictionCount++;}//System.out.println(String.format("removeLast.size:%s, key:%s,val:%s, size:%s", map.size(), key, value, mPoolSizeInBytes));entryRemoved(true, key, value, null);}public final Bitmap remove(@NonNull String key) {if (key == null) {throw new NullPointerException("key == null");}Bitmap previous;synchronized (this) {previous = map.remove(key);if (previous != null) {mPoolSizeInBytes -= previous.getByteCount();}}if (previous != null) {entryRemoved(false, key, previous, null);}return previous;}当关闭页面时,建议清除所有的数据
public final void clear() {int size = map.size();for (int i = 0; i < size; i++) {removeLast();}}
这是内存缓存类,可以设置为单例.
解码缓存池实现:
BitmapPool,也设置单例.
public static class FixedSimplePool<T> implements Pools.Pool<T> {private final Object[] mPool;private int mPoolSize;/*** Creates a new instance.** @param maxPoolSize The max pool size.* @throws IllegalArgumentException If the max pool size is less than zero.*/public FixedSimplePool(int maxPoolSize) {if (maxPoolSize <= 0) {throw new IllegalArgumentException("The max pool size must be > 0");}mPool = new Object[maxPoolSize];}@Override@SuppressWarnings("unchecked")public T acquire() {if (mPoolSize > 0) {final int lastPooledIndex = mPoolSize - 1;T instance = (T) mPool[lastPooledIndex];mPool[lastPooledIndex] = null;mPoolSize--;return instance;}return null;}@Overridepublic boolean release(@NonNull T instance) {if (isInPool(instance)) {return false;}if (mPoolSize < mPool.length) {mPool[mPoolSize] = instance;mPoolSize++;return true;}return false;}private boolean isInPool(@NonNull T instance) {for (int i = 0; i < mPoolSize; i++) {if (mPool[i] == instance) {return true;}}return false;}}
这段代码好像是sdk里面有的.忘了是不是了.就是实现了 pools接口,然后用数组去存储数据
整个pool向外提供两个方法,aquried,release.
public Bitmap acquire(int width, int height) {Bitmap b = simplePool.acquire();if (null == b) {b = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);} else {if (b.getHeight() == height && b.getWidth() == width) {//Log.d("TAG", String.format("use cache:%s-%s-%s%n", width, height, simplePool.mPoolSize));b.eraseColor(0);} else {b = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);}}return b;}public void release(Bitmap bitmap) {boolean isRelease = simplePool.release(bitmap);if (!isRelease) {System.out.println("recycle bitmap:" + bitmap);bitmap.recycle();}}
解码时的bitmap从这个单例里面取.而不是新建
val bm = BitmapPool.getInstance().acquire(width, height)
// val page = mupdfDocument?.loadPage(pageSize.index) ?: return null
至于什么时候release对象,这需要在确定不用bitmap时,把它加入到BitmapPool中.
相关文章:
android pdf框架-8,图片缓存
解码会产生很多图片,滑过后不要显示,如果直接回收,会浪费不少资源. 在没有缓存的情况下,会看到gc还是比较频繁的. 有了缓存后,明显gc少了. 目录 常用的缓存 自定义缓存 显示相关的内存缓存 解码缓存池 内存缓存实现: 解码缓存池实现: 常用的缓存 lrucache,这是最常用…...

UE5.2 SmartObject使用实践
SmartObject是UE5新出的一项针对AI的功能,可为开发者提供如公园长椅、货摊等交互对象的统一外观封装,如UE的CitySample(黑客帝国Demo)中就运用到了SmartObject。 但SmartObject实践起来较为繁琐,主要依赖于AI及行为树…...

奇舞周刊第521期:实现vue3响应式系统核心-MVP 模型
奇舞推荐 ■ ■ ■ 实现vue3响应式系统核心-MVP 模型 手把手带你实现一个 vue3 响应式系统,代码并没有按照源码的方式去进行组织,目的是学习、实现 vue3 响应式系统的核心,用最少的代码去实现最核心的能力,减少我们的学习负担&…...
Mybatis-plus手写SQL如何使用条件构造器和分页
Mybatis-plus手写SQL如何使用条件构造器和分页插件 前言:在使用mybatis-plus过程中,使用条件构造器和分页插件非常效率的提升开发速度,但有些业务需要使用连表查询,此时还想使用条件构造器和使用分页时应该如何操作呢?…...
Vue的table组件合并行方法
/*** param {Array} data - 原始数据集合* param {string} addParamer - 这个是自定义的参数,向每个对象中添加一个参数 按照这个参数的个数进行合并* param {} args - 剩余参数 这个是合并规则 ,比如按照时间合并 那就传入对象中的时间参数date…...
5. C语言字符串处理常用方法
在 C 语言中,字符串是以字符数组的形式表示的,以空字符 \0 结尾。C 语言提供了一系列的字符串处理函数,可以用于字符串的操作、查找、比较等。以下是一些常用的 C 语言字符串处理函数: 1. 字符串定义与初始化 #include <stdio.h> #include <string.h>int mai…...

ts--(入门到离职系列)
TS 与 JS 的区别 TypeScript[4] 是一种由微软开发的自由和开源的编程语言。它是 JavaScript 的一个超集,而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。-- 官方文档 说人话就是 TS 拓展了 JS 的一些功能,解决了 JS 的一些缺点&#…...
java后端常见问题
java面向对象的特征,如何应用 面向对象编程是利用类和对象的编程思想万物皆成类,对象是类的具体体现,面向对象的三大基础特性,继承封装多态。、封装:封装隐藏了类的具体内部实现机制,可以在不影响使用的情…...

windows系统玩游戏找不到d3dx9_43.dll缺失,无法启动此程序的解决方法
今日,我们要深入讨论d3dx9_43.dll文件的重要性及其缺失问题。最近,我也遇到了这个文件丢失的困扰,因此想借此机会与大家分享如何解决d3dx9_43.dll缺失的问题。 一.电脑d3dx9_43.dll丢失会提示什么? 关于电脑提示d3dx9_43.dll丢失…...
MATLAB中mapminmax函数用法
目录 语法 说明 示例 使用 mapminmax 函数格式化矩阵 mapminmax函数的功能是通过将行最小值和最大值映射到 [-1 1] 来处理矩阵。 语法 [Y,PS] mapminmax(X,YMIN,YMAX) [Y,PS] mapminmax(X,FP) Y mapminmax(apply,X,PS) X mapminmax(reverse,Y,PS) dx_dy mapminmax(d…...
数据结构导航 -- 38篇
数据结构实现代码 线性表 顺序表代码-C-CSDN博客 单链表代码-C-CSDN博客 双链表代码-C-CSDN博客 有序表概述-CSDN博客 栈 栈代码数组实现-C-CSDN博客 栈代码链表实现(链栈)-C-CSDN博客 队列 队列与环形队列顺序存储代码数组实现-C-CSDN博客 队…...

前端性能优化 | CDN缓存
前言 CDN(Content Delivery Network)是一种分布式的网络架构,通过在全球各地部署节点服务器来快速传输和分发网络内容。CDN的主要目标是提供快速、可靠的内容传输,以提升用户体验。 本文主要从以下方面讲解CDN 什么是CDNCDN的作…...

【C#语言入门】17. 事件详解(上)
【C#语言入门】17. 事件详解(上) 一、初步了解事件 定义:单词Event,译为“事件” 通顺的解释就是**“能够发生的什么事情”**,例如,“苹果”不能发生,但是“公司上市”这件事能发生。在C#中事…...
Charles无法打开导出的har文件解决方法
打开出错:MalformedJson: Use JsonReader.setLenient(true) to accept malformed JSON at line1 column 1368184 path $.log.entries[41].request.postData.text 一、解决办法 用json.dumps格式化一下里面内容,保存为新文件再打开 import jsondef modify…...
FFmpeg--FlvPaser源码:解析.flv输出.h264
文章目录 程序功能:函数调用流程:部分FlvParse.h部分FlvParse.cpp 程序功能: 解析flv文件,重写一个h264文件,如输入movie.flv , 输出movie.h264 (只有视频,没有声音) 函数调用流程: 1 Proce…...

【项目笔记】java微服务:黑马头条(day02)
文章目录 app端文章查看,静态化freemarker,分布式文件系统minIO1)文章列表加载1.1)需求分析1.2)表结构分析1.3)导入文章数据库1.3.1)导入数据库1.3.2)导入对应的实体类 1.4)实现思路1.5)接口定义1.6)功能实现1.6.1):导入heima-leadnews-article微服务&am…...

每天五分钟计算机视觉:图像数据不足带来的问题和解决办法
本文重点 在当今的数字时代,图像数据的应用已经渗透到各个领域,包括但不限于计算机视觉、机器学习、自动驾驶、医疗诊断等。然而,当图像数据不足时,会引发一系列问题,对相关应用产生负面影响。 尤其是计算机视觉领域,图像数据尤为珍贵和稀缺,如果计算机视觉的任务中,如…...
手机App防沉迷系统C卷(JavaPythonC++Node.jsC语言)
智能手机方便了我们生活的同时,也侵占了我们不少的时间。"手机App防沉迷系统"能够让我们每天合理的规划手机App使用时间,在正确的时间做正确的事。 它的大概原理是这样的: 1、在一天24小时内,可注册每个App的允许使用时段; 2、一个时段只能使用一个App,举例说明…...
【WEEK2】学习目标及总结【SpringMVC】【中文版】
学习目标: 三周完成SpringMVC入门——第二周 学习内容: 参考视频教程【狂神说Java】SpringMVC最新教程IDEA版通俗易懂使用注释完成MVC程序Controller控制器RestFul风格结果跳转方式数据处理 学习时间及产出: 第二周 MON~FRI 2024.3.4 【W…...

Git版本工具学习
目录 版本控制git配置工作区域文件状态git对象模型基础命令.gitignore忽略文件IDEA集成Git 版本控制 本地版本控制:在本地记录每一次版本更新。 集中版本控制:版本数据都保存在单一服务器,不联网就看不到版本信息。SVN 分布式版本控制&…...
PTC过流保护器件工作原理及选型方法
PTC过流保护器件 (Positive Temperature Coefficient,正温度系数热敏电阻)是一种过流保护元件,其工作原理基于电阻值随温度变化的特性。当电路正常工作时,PTC的阻值很小,电流可以顺畅通过;但当…...

联想拯救者R9000P 网卡 Realtek 8852CE Ubuntu/Mint linux 系统睡眠后,无线网卡失效
联想拯救者R9000P 网卡型号 Realtek PCle GbE Family Controller Realtek 8852CE WiFi 6E PCI-E NIC 系统版本 Ubuntu 24.04 / mint 22.1 问题现象 rtw89_8852ce,Link is Down,xtal si not ready,mac init fail,xtal si not …...

AI大数据模型如何与thingsboard物联网结合
一、 AI大数据与ThingsBoard物联网的结合可以从以下几个方面实现: 1. 数据采集与集成 设备接入:ThingsBoard支持多种通信协议(如MQTT、CoAP、HTTP、Modbus、OPC-UA等),可以方便地接入各种物联网设备。通过这些协议&am…...
业态即战场:零售平台的生意模型与系统设计解构
目录 一、当我们在电商买菜、点外卖时,其实是零售业态在进化 (一)从“商场选货”到“算法推货”:零售的时代已经不同 (二)“控货”和“卖场”——零售的两种基本商业模式 二、四种经典零售业态解析:控货 vs 卖场,地面 vs 线上 (一)地面控货零售:直营模式的黄金…...
App使用webview套壳引入h5(三)——解决打包为app后在安卓机可物理返回但是在苹果手机无法测滑返回的问题
话不多说,直接放最终版本代码。 解决思路是:如果设备是ios设备在myH5中监听 touchstart 和touchend事件。 经过 App使用webview套壳引入h5的最终代码如下 myApp中,entry.vue代码如下: <template><view class"ent…...
大数据量高实时性场景下订单生成的优化方案
文章目录 一、问题背景二、核心优化目标三、架构设计方案3.1 分层架构设计 3.2 关键组件说明 四、核心优化策略4.1 异步处理与流量控制4.1.1 异步接口设计4.1.2 任务进度查询 4.2 批量处理与并行计算4.2.1 数据分批处理4.2.2 并行流处理 4.3 数据库优化4.3.1 批量插入4.3.2 索…...

BugKu Web渗透之网站被hei(仅仅是ctf题目名称)
启动场景,打开网页,显示如下: 目前没有看出任何异常。 步骤一: 右键查看源代码。源代码较多,也没发现异常。 步骤二: 用dirsearch扫描网站目录。 如图: 看起来shell.php很可疑。 步骤三&…...

矩阵QR分解
1 orthonormal 向量与 Orthogonal 矩阵 orthonormal 向量定义为 ,任意向量 相互垂直,且模长为1; 如果将 orthonormal 向量按列组织成矩阵,矩阵为 Orthogonal 矩阵,满足如下性质: ; 当为方阵时&…...

【数据分析】基于adonis2与pairwise.adonis2的群组差异分析教程
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包数据下载导入数据数据预处理adonis分析pairwise.adonis2分析总结系统信息介绍 本教程主要用于执行和分析基于距离矩阵的多样性和群落结构分析,特别是通过adonis2和pairwi…...
vue3 按钮级别权限控制
在Vue 3中实现按钮级别的权限控制,可以通过多种方式实现。这里我将介绍几种常见的方法: 方法1:使用Vue 3的Composition API 在Vue 3中,你可以使用Composition API来创建一个可复用的逻辑来处理权限控制。 创建权限控制逻辑 首…...