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

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

相关文章

Linux创建服务使用systemctl管理详解

《Linux创建服务使用systemctl管理详解》文章指导在Linux中创建systemd服务,设置文件权限为所有者读写、其他只读,重新加载配置,启动服务并检查状态,确保服务正常运行,关键步骤包括权... 目录创建服务 /usr/lib/systemd/system/设置服务文件权限:所有者读写js,其他

Java高效实现PowerPoint转PDF的示例详解

《Java高效实现PowerPoint转PDF的示例详解》在日常开发或办公场景中,经常需要将PowerPoint演示文稿(PPT/PPTX)转换为PDF,本文将介绍从基础转换到高级设置的多种用法,大家... 目录为什么要将 PowerPoint 转换为 PDF安装 Spire.Presentation fo

在Node.js中使用.env文件管理环境变量的全过程

《在Node.js中使用.env文件管理环境变量的全过程》Node.js应用程序通常依赖于环境变量来管理敏感信息或配置设置,.env文件已经成为一种流行的本地管理这些变量的方法,本文将探讨.env文件... 目录引言为什么使php用 .env 文件 ?如何在 Node.js 中使用 .env 文件最佳实践引

C#实现SHP文件读取与地图显示的完整教程

《C#实现SHP文件读取与地图显示的完整教程》在地理信息系统(GIS)开发中,SHP文件是一种常见的矢量数据格式,本文将详细介绍如何使用C#读取SHP文件并实现地图显示功能,包括坐标转换、图形渲染、平... 目录概述功能特点核心代码解析1. 文件读取与初始化2. 坐标转换3. 图形绘制4. 地图交互功能缩放

python库pydantic数据验证和设置管理库的用途

《python库pydantic数据验证和设置管理库的用途》pydantic是一个用于数据验证和设置管理的Python库,它主要利用Python类型注解来定义数据模型的结构和验证规则,本文给大家介绍p... 目录主要特点和用途:Field数值验证参数总结pydantic 是一个让你能够 confidentl

C#使用Spire.Doc for .NET实现HTML转Word的高效方案

《C#使用Spire.Docfor.NET实现HTML转Word的高效方案》在Web开发中,HTML内容的生成与处理是高频需求,然而,当用户需要将HTML页面或动态生成的HTML字符串转换为Wor... 目录引言一、html转Word的典型场景与挑战二、用 Spire.Doc 实现 HTML 转 Word1

SpringBoot 多环境开发实战(从配置、管理与控制)

《SpringBoot多环境开发实战(从配置、管理与控制)》本文详解SpringBoot多环境配置,涵盖单文件YAML、多文件模式、MavenProfile分组及激活策略,通过优先级控制灵活切换环境... 目录一、多环境开发基础(单文件 YAML 版)(一)配置原理与优势(二)实操示例二、多环境开发多文件版

Redis实现高效内存管理的示例代码

《Redis实现高效内存管理的示例代码》Redis内存管理是其核心功能之一,为了高效地利用内存,Redis采用了多种技术和策略,如优化的数据结构、内存分配策略、内存回收、数据压缩等,下面就来详细的介绍... 目录1. 内存分配策略jemalloc 的使用2. 数据压缩和编码ziplist示例代码3. 优化的

SpringBoot集成XXL-JOB实现任务管理全流程

《SpringBoot集成XXL-JOB实现任务管理全流程》XXL-JOB是一款轻量级分布式任务调度平台,功能丰富、界面简洁、易于扩展,本文介绍如何通过SpringBoot项目,使用RestTempl... 目录一、前言二、项目结构简述三、Maven 依赖四、Controller 代码详解五、Service

深入解析C++ 中std::map内存管理

《深入解析C++中std::map内存管理》文章详解C++std::map内存管理,指出clear()仅删除元素可能不释放底层内存,建议用swap()与空map交换以彻底释放,针对指针类型需手动de... 目录1️、基本清空std::map2️、使用 swap 彻底释放内存3️、map 中存储指针类型的对象