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

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

相关文章

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... 目录背景介绍目的和范围预期读者文档结构概述术语表核心概念与联系故事引入核心概念解释核心概念之间的关系

SpringSecurity显示用户账号已被锁定的原因及解决方案

《SpringSecurity显示用户账号已被锁定的原因及解决方案》SpringSecurity中用户账号被锁定问题源于UserDetails接口方法返回值错误,解决方案是修正isAccountNon... 目录SpringSecurity显示用户账号已被锁定的解决方案1.问题出现前的工作2.问题出现原因各

SpringMVC高效获取JavaBean对象指南

《SpringMVC高效获取JavaBean对象指南》SpringMVC通过数据绑定自动将请求参数映射到JavaBean,支持表单、URL及JSON数据,需用@ModelAttribute、@Requ... 目录Spring MVC 获取 JavaBean 对象指南核心机制:数据绑定实现步骤1. 定义 Ja

C++高效内存池实现减少动态分配开销的解决方案

《C++高效内存池实现减少动态分配开销的解决方案》C++动态内存分配存在系统调用开销、碎片化和锁竞争等性能问题,内存池通过预分配、分块管理和缓存复用解决这些问题,下面就来了解一下... 目录一、C++内存分配的性能挑战二、内存池技术的核心原理三、主流内存池实现:TCMalloc与Jemalloc1. TCM

使用jenv工具管理多个JDK版本的方法步骤

《使用jenv工具管理多个JDK版本的方法步骤》jenv是一个开源的Java环境管理工具,旨在帮助开发者在同一台机器上轻松管理和切换多个Java版本,:本文主要介绍使用jenv工具管理多个JD... 目录一、jenv到底是干啥的?二、jenv的核心功能(一)管理多个Java版本(二)支持插件扩展(三)环境隔

Python基于微信OCR引擎实现高效图片文字识别

《Python基于微信OCR引擎实现高效图片文字识别》这篇文章主要为大家详细介绍了一款基于微信OCR引擎的图片文字识别桌面应用开发全过程,可以实现从图片拖拽识别到文字提取,感兴趣的小伙伴可以跟随小编一... 目录一、项目概述1.1 开发背景1.2 技术选型1.3 核心优势二、功能详解2.1 核心功能模块2.

基于Python构建一个高效词汇表

《基于Python构建一个高效词汇表》在自然语言处理(NLP)领域,构建高效的词汇表是文本预处理的关键步骤,本文将解析一个使用Python实现的n-gram词频统计工具,感兴趣的可以了解下... 目录一、项目背景与目标1.1 技术需求1.2 核心技术栈二、核心代码解析2.1 数据处理函数2.2 数据处理流程

RedisTemplate默认序列化方式显示中文乱码的解决

《RedisTemplate默认序列化方式显示中文乱码的解决》本文主要介绍了SpringDataRedis默认使用JdkSerializationRedisSerializer导致数据乱码,文中通过示... 目录1. 问题原因2. 解决方案3. 配置类示例4. 配置说明5. 使用示例6. 验证存储结果7.

Python中bisect_left 函数实现高效插入与有序列表管理

《Python中bisect_left函数实现高效插入与有序列表管理》Python的bisect_left函数通过二分查找高效定位有序列表插入位置,与bisect_right的区别在于处理重复元素时... 目录一、bisect_left 基本介绍1.1 函数定义1.2 核心功能二、bisect_left 与