高效的显示位图(五):管理位图内…

2024-05-03 00:38
文章标签 高效 显示 管理 位图

本文主要是介绍高效的显示位图(五):管理位图内…,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

- 除了缓冲机制,还有其它措施可以用来为垃圾回收和位图重用增加便利
- 针对不同版本:
  • Android 2.2及以前版本,当垃圾回收启动,应用中的线程全部停止,这导致性能损失,Android 2.3.3引入并发垃圾回收机制
  • Android 2.3.3及更早版本,像素数据存储在本地内存,与为图对象(存储于虚拟机堆)本身隔离。本地内存数据无法以可以预知的方式释放,致使程序可能超过内存限制而崩溃。Android 3.0以后,像素数据也存储于虚拟机堆
- 本篇展示如何根据不同版本优化位图内存管理

Android 2.3.3以下版本内存管理
- recycle()方法:允许应用尽快回收内存
private int mCacheRefCount = 0;
private int mDisplayRefCount = 0;
...
// Notify the drawable that the displayed state has changed.
// Keep a count to determine when the drawable is no longer displayed.
public void setIsDisplayed(boolean isDisplayed) {
 
synchronized (this) {
     
if (isDisplayed) {
          mDisplayRefCount
++;
          mHasBeenDisplayed
= true;
     
} else {
          mDisplayRefCount
--;
     
}
 
}
 
// Check to see if recycle() can be called.
  checkState
();
}

// Notify the drawable that the cache state has changed.
// Keep a count to determine when the drawable is no longer being cached.
public void setIsCached(boolean isCached) {
 
synchronized (this) {
     
if (isCached) {
          mCacheRefCount
++;
     
} else {
          mCacheRefCount
--;
     
}
 
}
 
// Check to see if recycle() can be called.
  checkState
();
}

private synchronized void checkState() {
 
// If the drawable cache and display ref counts = 0, and this drawable
 
// has been displayed, then recycle.
 
if (mCacheRefCount <= 0 && mDisplayRefCount <= 0 && mHasBeenDisplayed
         
&& hasValidBitmap()) {
      getBitmap
().recycle();
 
}
}

private synchronized boolean hasValidBitmap() {
 
Bitmap bitmap = getBitmap();
 
return bitmap != null && !bitmap.isRecycled();
}

Android 3.0以上版本内存管理
- BitmapFactory.Options.inBitmap:解码器将尝试重用已经存在的位图对象:
  • 被重用的位图对象必须与源内容大小一致,并且是JPG或PNG格式
  • 被重用的位图的configuration将覆盖inPreferredConfig设置,如果有的话
  • 你应该使用解码方法返回的位图对象。被重用的位图不一定还能用
* 保存一个位图待用:
- 如何保存一个已经存在的位图
HashSet<SoftReference<Bitmap>> mReusableBitmaps;
private LruCache<String, BitmapDrawable> mMemoryCache;

// If you're running on Honeycomb or newer, create
// a HashSet of references to reusable bitmaps.
if (Utils.hasHoneycomb()) {
  mReusableBitmaps
= new HashSet<SoftReference<Bitmap>>();
}

mMemoryCache
= new LruCache<String, BitmapDrawable>(mCacheParams.memCacheSize) {

 
// Notify the removed entry that is no longer being cached.
 
@Override
 
protected void entryRemoved(boolean evicted, String key,
         
BitmapDrawable oldValue, BitmapDrawable newValue) {
     
if (RecyclingBitmapDrawable.class.isInstance(oldValue)) {
         
// The removed entry is a recycling drawable, so notify it
         
// that it has been removed from the memory cache.
         
((RecyclingBitmapDrawable) oldValue).setIsCached(false);
     
} else {
         
// The removed entry is a standard BitmapDrawable.
         
if (Utils.hasHoneycomb()) {
             
// We're running on Honeycomb or later, so add the bitmap
             
// to a SoftReference set for possible use with inBitmap later.
              mReusableBitmaps
.add
                     
(new SoftReference<Bitmap>(oldValue.getBitmap()));
         
}
     
}
 
}
....
}

* 使用现有的位图:
- 解码方法检查是否有现存的位图可用:
public static Bitmap decodeSampledBitmapFromFile(String filename,
     
int reqWidth, int reqHeight, ImageCache cache) {

 
final BitmapFactory.Options options = new BitmapFactory.Options();
 
...
 
BitmapFactory.decodeFile(filename, options);
 
...

 
// If we're running on Honeycomb or newer, try to use inBitmap.
 
if (Utils.hasHoneycomb()) {
      addInBitmapOptions
(options, cache);
 
}
 
...
 
return BitmapFactory.decodeFile(filename, options);
}
- addInBitmapOptions():
private static void addInBitmapOptions(BitmapFactory.Options options,
     
ImageCache cache) {
 
// inBitmap only works with mutable bitmaps, so force the decoder to
 
// return mutable bitmaps.
  options
.inMutable = true;

 
if (cache != null) {
     
// Try to find a bitmap to use for inBitmap.
     
Bitmap inBitmap = cache.getBitmapFromReusableSet(options);

     
if (inBitmap != null) {
         
// If a suitable bitmap has been found, set it as the value of
         
// inBitmap.
          options
.inBitmap = inBitmap;
     
}
 
}
}

// This method iterates through the reusable bitmaps, looking for one
// to use for inBitmap:
protected Bitmap getBitmapFromReusableSet(BitmapFactory.Options options) {
     
Bitmap bitmap = null;

 
if (mReusableBitmaps != null && !mReusableBitmaps.isEmpty()) {
     
final Iterator<SoftReference<Bitmap>> iterator
             
= mReusableBitmaps.iterator();
     
Bitmap item;

     
while (iterator.hasNext()) {
          item
= iterator.next().get();

         
if (null != item && item.isMutable()) {
             
// Check to see it the item can be used for inBitmap.
             
if (canUseForInBitmap(item, options)) {
                  bitmap
= item;

                 
// Remove from reusable set so it can't be used again.
                  iterator
.remove();
                 
break;
             
}
         
} else {
             
// Remove from the set if the reference has been cleared.
              iterator
.remove();
         
}
     
}
 
}
 
return bitmap;
}
- 最后,此方法检查找到的位图对象是否可用:
private static boolean canUseForInBitmap(
     
Bitmap candidate, BitmapFactory.Options targetOptions) {
 
int width = targetOptions.outWidth / targetOptions.inSampleSize;
 
int height = targetOptions.outHeight / targetOptions.inSampleSize;

 
// Returns true if "candidate" can be used for inBitmap re-use with
 
// "targetOptions".
 
return candidate.getWidth() == width && candidate.getHeight() == height;
}

这篇关于高效的显示位图(五):管理位图内…的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/955476

相关文章

在macOS上安装jenv管理JDK版本的详细步骤

《在macOS上安装jenv管理JDK版本的详细步骤》jEnv是一个命令行工具,正如它的官网所宣称的那样,它是来让你忘记怎么配置JAVA_HOME环境变量的神队友,:本文主要介绍在macOS上安装... 目录前言安装 jenv添加 JDK 版本到 jenv切换 JDK 版本总结前言China编程在开发 Java

Spring Boot Actuator应用监控与管理的详细步骤

《SpringBootActuator应用监控与管理的详细步骤》SpringBootActuator是SpringBoot的监控工具,提供健康检查、性能指标、日志管理等核心功能,支持自定义和扩展端... 目录一、 Spring Boot Actuator 概述二、 集成 Spring Boot Actuat

MySQL多实例管理如何在一台主机上运行多个mysql

《MySQL多实例管理如何在一台主机上运行多个mysql》文章详解了在Linux主机上通过二进制方式安装MySQL多实例的步骤,涵盖端口配置、数据目录准备、初始化与启动流程,以及排错方法,适用于构建读... 目录一、什么是mysql多实例二、二进制方式安装MySQL1.获取二进制代码包2.安装基础依赖3.清

在IntelliJ IDEA中高效运行与调试Spring Boot项目的实战步骤

《在IntelliJIDEA中高效运行与调试SpringBoot项目的实战步骤》本章详解SpringBoot项目导入IntelliJIDEA的流程,教授运行与调试技巧,包括断点设置与变量查看,奠定... 目录引言:为良驹配上好鞍一、为何选择IntelliJ IDEA?二、实战:导入并运行你的第一个项目步骤1

使用Python构建一个高效的日志处理系统

《使用Python构建一个高效的日志处理系统》这篇文章主要为大家详细讲解了如何使用Python开发一个专业的日志分析工具,能够自动化处理、分析和可视化各类日志文件,大幅提升运维效率,需要的可以了解下... 目录环境准备工具功能概述完整代码实现代码深度解析1. 类设计与初始化2. 日志解析核心逻辑3. 文件处

Java docx4j高效处理Word文档的实战指南

《Javadocx4j高效处理Word文档的实战指南》对于需要在Java应用程序中生成、修改或处理Word文档的开发者来说,docx4j是一个强大而专业的选择,下面我们就来看看docx4j的具体使用... 目录引言一、环境准备与基础配置1.1 Maven依赖配置1.2 初始化测试类二、增强版文档操作示例2.

Windows环境下解决Matplotlib中文字体显示问题的详细教程

《Windows环境下解决Matplotlib中文字体显示问题的详细教程》本文详细介绍了在Windows下解决Matplotlib中文显示问题的方法,包括安装字体、更新缓存、配置文件设置及编码調整,并... 目录引言问题分析解决方案详解1. 检查系统已安装字体2. 手动添加中文字体(以SimHei为例)步骤

Spring Boot集成Druid实现数据源管理与监控的详细步骤

《SpringBoot集成Druid实现数据源管理与监控的详细步骤》本文介绍如何在SpringBoot项目中集成Druid数据库连接池,包括环境搭建、Maven依赖配置、SpringBoot配置文件... 目录1. 引言1.1 环境准备1.2 Druid介绍2. 配置Druid连接池3. 查看Druid监控

Knife4j+Axios+Redis前后端分离架构下的 API 管理与会话方案(最新推荐)

《Knife4j+Axios+Redis前后端分离架构下的API管理与会话方案(最新推荐)》本文主要介绍了Swagger与Knife4j的配置要点、前后端对接方法以及分布式Session实现原理,... 目录一、Swagger 与 Knife4j 的深度理解及配置要点Knife4j 配置关键要点1.Spri

在Golang中实现定时任务的几种高效方法

《在Golang中实现定时任务的几种高效方法》本文将详细介绍在Golang中实现定时任务的几种高效方法,包括time包中的Ticker和Timer、第三方库cron的使用,以及基于channel和go... 目录背景介绍目的和范围预期读者文档结构概述术语表核心概念与联系故事引入核心概念解释核心概念之间的关系