iis服务器助手广告广告
返回顶部
首页 > 资讯 > 移动开发 >Bitmap引起的OOM问题
  • 178
分享到

Bitmap引起的OOM问题

Bitmap引起的OOM问题Bitmap OOM 2023-05-18 05:05:14 178人浏览 八月长安
摘要

目录1.什么是OOM?为什么会引起OOM?2.避免Bitmap引起的OOM技巧小结1)采用低内存占用量的编码方式2)图片压缩3.及时回收图像4.其他方法1.简单通过SoftRefer

1.什么是OOM?为什么会引起OOM?

答:Out Of Memory(内存溢出),我们都知道Android系统会为每个APP分配一个独立的工作空间,或者说分配一个单独的Dalvik虚拟机,这样每个APP都可以独立运行而不相互影响!而Android对于每个Dalvik虚拟机都会有一个最大内存限制,如果当前占用的内存加上我们申请的内存资源超过了这个限制,系统就会抛出OOM错误!另外,这里别和RAM混淆了,即时当前RAM中剩余的内存有1G多,但是OOM还是会发生!别把RAM(物理内存)和OOM扯到一起!另外RAM不足的话,就是杀应用了,而不是仅仅是OOM了!而这个Dalvik中的最大内存标准,不同的机型是不一样的,可以调用:

ActivityManager activityManager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
Log.e("HEHE","最大内存:" + activityManager.getMemoryClass());

获得正常的最大内存标准,又或者直接在命令行键入:

adb shell getprop | grep dalvik.vm.heapgrowthlimit

你也可以打开系统源码/system/build.prop文件,看下文件中这一部分的信息得出:

dalvik.vm.heapstartsize=8m
dalvik.vm.heapgrowthlimit=192m
dalvik.vm.heapsize=512m
dalvik.vm.heaptargetutilization=0.75
dalvik.vm.heapminfree=2m
dalvik.vm.heapmaxfree=8m

你也可以试试自己手头的机子~

好啦,不扯了,关于OOM问题的产生,就扯到这里,再扯就到内存管理那一块了,可是个大块头,现在还啃不动...下面我们来看下避免Bitmap OOM的一些技巧吧!

2.避免Bitmap引起的OOM技巧小结

1)采用低内存占用量的编码方式

上一节说了BitmapFactory.Options这个类,我们可以设置下其中的inPreferredConfig属性,默认是Bitmap.Config.ARGB_8888,我们可以修改成Bitmap.Config.ARGB_4444Bitmap.Config ARGB_4444:每个像素占四位,即A=4,R=4,G=4,B=4,那么一个像素点占4+4+4+4=16位Bitmap.Config ARGB_8888:每个像素占八位,即A=8,R=8,G=8,B=8,那么一个像素点占8+8+8+8=32位默认使用ARGB_8888,即一个像素占4个字节!

2)图片压缩

同样是BitmapFactory.Options,我们通过inSampleSize设置缩放倍数,比如写2,即长宽变为原来的1/2,图片就是原来的1/4,如果不进行缩放的话设置为1即可!但是不能一味的压缩,毕竟这个值太小的话,图片会很模糊,而且要避免图片的拉伸变形,所以需要我们在程序中动态的计算,这个inSampleSize的合适值,而Options中又有这样一个方法:inJustDecodeBounds,将该参数设置为true后,decodeFiel并不会分配内存空间,但是可以计算出原始图片的长宽,调用options.outWidth/outHeight获取出图片的宽高,然后通过一定的算法,即可得到适合的inSampleSize,这里感谢街神提供的代码——摘自鸿洋blog!

public static int caculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
    int width = options.outWidth;
    int height = options.outHeight;
    int inSampleSize = 1;
    if (width > reqWidth || height > reqHeight) {
        int widthRadio = Math.round(width * 1.0f / reqWidth);
        int heightRadio = Math.round(height * 1.0f / reqHeight);
        inSampleSize = Math.max(widthRadio, heightRadio);
    }
    return inSampleSize;
}

然后使用下上述的方法即可:

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true; // 设置了此属性一定要记得将值设置为false
Bitmap bitmap = null;
bitmap = BitmapFactory.decodeFile(url, options);
options.inSampleSize = computeSampleSize(options,128,128);
options.inPreferredConfig = Bitmap.Config.ARGB_4444;
  
options.inPurgeable = true;
options.inInputShareable = true;
options.inJustDecodeBounds = false;
try {
    bitmap = BitmapFactory.decodeFile(url, options);
} catch (OutOfMemoryError e) {
        Log.e(TAG, "OutOfMemoryError");
}

3.及时回收图像

如果引用了大量的Bitmap对象,而应用又不需要同时显示所有图片。可以将暂时不用到的Bitmap对象及时回收掉。对于一些明确知道图片使用情况的场景可以主动recycle回收,比如引导页的图片,使用完就recycle,帧动画,加载一张,画一张,释放一张!使用时加载,不显示时直接置null或recycle!比如:imageView.setImageResource(0); 不过某些情况下会出现特定图片反复加载,释放,再加载等,低效率的事情...

4.其他方法

下面这些方法,我并没有用过,大家可以自行查阅相关资料:

1.简单通过SoftReference引用方式管理图片资源

建个SoftReference的HashMap使用图片时先查询这个hashmap是否有softreference, softreference里的图片是否为空,如果为空就加载图片到softreference并加入hashmap。无需再代码里显式的处理图片的回收与释放,GC会自动处理资源的释放。这种方式处理起来简单实用,能一定程度上避免前一种方法反复加载释放的低效率。但还不够优化

示例代码:

private Map<String, SoftReference<Bitmap>> imageMap 
                                           = new HashMap<String, SoftReference<Bitmap>>();

public Bitmap loadBitmap(final String imageUrl,final ImageCallBack imageCallBack) {
    SoftReference<Bitmap> reference = imageMap.get(imageUrl);
    if(reference != null) {
        if(reference.get() != null) {
            return reference.get();
        }
    }
    final Handler handler = new Handler() {
        public void handleMessage(final android.os.Message msg) {
            //加入到缓存中
            Bitmap bitmap = (Bitmap)msg.obj;
            imageMap.put(imageUrl, new SoftReference<Bitmap>(bitmap));
            if(imageCallBack != null) {
                imageCallBack.getBitmap(bitmap);
            }
        }
    };
    new Thread(){
        public void run() {
            Message message = handler.obtainMessage();
            message.obj = downloadBitmap(imageUrl);
            handler.sendMessage(message);
        }
    }.start();
    return null ;
}

// 从网上下载图片
private Bitmap downloadBitmap (String imageUrl) {
    Bitmap bitmap = null;
    try {
        bitmap = BitmapFactory.decodeStream(new URL(imageUrl).openStream());
        return bitmap ;
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    } 
}
public interface ImageCallBack{
    void getBitmap(Bitmap bitmap);
}

2.LruCache + sd的缓存方式

Android 3.1版本起,官方还提供了LruCache来进行cache处理,当存储Image的大小大于LruCache 设定的值,那么近期使用次数最少的图片就会被回收掉,系统会自动释放内存!

使用示例

步骤:

1)要先设置缓存图片的内存大小,我这里设置为手机内存的1/8,手机内存的获取方式:int MAXMEMONRY = (int) (Runtime.getRuntime() .maxMemory() / 1024);

2)LruCache里面的键值对分别是URL和对应的图片

3)重写了一个叫做sizeOf的方法,返回的是图片数量。

private LruCache<String, Bitmap> mMemoryCache;
private LruCacheUtils() {
    if (mMemoryCache == null)
        mMemoryCache = new LruCache<String, Bitmap>(
                MAXMEMONRY / 8) {
            @Override
            protected int sizeOf(String key, Bitmap bitmap) {
                // 重写此方法来衡量每张图片的大小,默认返回图片数量。
                return bitmap.getRowBytes() * bitmap.getHeight() / 1024;
            }

            @Override
            protected void entryRemoved(boolean evicted, String key,
                    Bitmap oldValue, Bitmap newValue) {
                Log.v("tag", "hard cache is full , push to soft cache");
               
            }
        };
}

4)下面的方法分别是清空缓存、添加图片到缓存、从缓存中取得图片、从缓存中移除。

移除和清除缓存是必须要做的事,因为图片缓存处理不当就会报内存溢出,所以一定要引起注意。

public void clearCache() {
    if (mMemoryCache != null) {
        if (mMemoryCache.size() > 0) {
            Log.d("CacheUtils",
                    "mMemoryCache.size() " + mMemoryCache.size());
            mMemoryCache.evictAll();
            Log.d("CacheUtils", "mMemoryCache.size()" + mMemoryCache.size());
        }
        mMemoryCache = null;
    }
}

public synchronized void addBitmapToMemoryCache(String key, Bitmap bitmap) {
    if (mMemoryCache.get(key) == null) {
        if (key != null && bitmap != null)
            mMemoryCache.put(key, bitmap);
    } else
        Log.w(TAG, "the res is aready exits");
}

public synchronized Bitmap getBitmapFromMemCache(String key) {
    Bitmap bm = mMemoryCache.get(key);
    if (key != null) {
        return bm;
    }
    return null;
}


public synchronized void removeImageCache(String key) {
    if (key != null) {
        if (mMemoryCache != null) {
            Bitmap bm = mMemoryCache.remove(key);
            if (bm != null)
                bm.recycle();
        }
    }
}

到此这篇关于Bitmap引起的OOM问题的文章就介绍到这了,更多相关Bitmap OOM内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Bitmap引起的OOM问题

本文链接: https://www.lsjlt.com/news/211733.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Bitmap引起的OOM问题
    目录1.什么是OOM?为什么会引起OOM?2.避免Bitmap引起的OOM技巧小结1)采用低内存占用量的编码方式2)图片压缩3.及时回收图像4.其他方法1.简单通过SoftRefer...
    99+
    2023-05-18
    Bitmap引起的OOM问题 Bitmap OOM
  • SpringBootActuator潜在的OOM问题的解决
    目录背景&问题问题原因及解决默认埋点是如何生效的http.client.requests 中的 uri解决会不会 OOM此问题背景产生于近期需要上线的一个功能的埋点;主要表现...
    99+
    2024-04-02
  • 如何解决React.memo引起的bug问题
    这篇文章主要介绍如何解决React.memo引起的bug问题,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!与PureComponent不同的是PureComponent只是进行浅对比props来决定是否跳过更新数据这...
    99+
    2023-06-29
  • 一个RESOURCE MANAGER引起的问题分析
    1.分析hanganalyze日志: Chains most likely to have caused   the hang: 《《《最 终 阻塞源都...
    99+
    2024-04-02
  • JavaRMI引起的log4j漏洞问题重现
    目录RMI和JNDIRMI模拟漏洞重现【紧急补救措施3选1】2021-12-10日左右,java的log4j框架出现了一个大漏洞,对服务器案例引起了不小的影响,当然只对于log4j的...
    99+
    2024-04-02
  • Java RMI引起的log4j漏洞问题分析
    这篇文章主要介绍“Java RMI引起的log4j漏洞问题分析”,在日常操作中,相信很多人在Java RMI引起的log4j漏洞问题分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Jav...
    99+
    2023-06-22
  • Double类型精度问题引起的错误
    场景说明 研发同事让把某个double类型字段的值四舍五入保留2位小数,mysql中round(col,2)可以实现四舍五入并且保留2位小数,但是神奇的事情发生了:发现有的四舍五入是正确的,而有...
    99+
    2024-04-02
  • MySQL-JDBC驱动引起bug问题的示例
    这篇文章给大家分享的是有关MySQL-JDBC驱动引起bug问题的示例的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。问题背景公司是做电商系统的,整个系统搭建在华为云上。系统设计的...
    99+
    2024-04-02
  • Java中Controller引起的Ambiguous mapping问题及解决
    目录Controller引起的Ambiguous mapping问题问题描述解决办法Ambiguous mapping(模糊映射)小白的报错日常解决办法Controller引起的Am...
    99+
    2022-11-13
    Java Controller Ambiguous mapping Controller Ambiguous mapping
  • 一次rman恢复引起的nologging问题模拟
    测试环境:Oracle 11.2.0.4SLES 11SP4结论如下:no force logging,table nologging, dml nologging,出现ora-26040no force logging,table log...
    99+
    2023-06-06
  • 如何解决SpringBoot Actuator潜在的OOM问题
    这篇文章主要介绍如何解决SpringBoot Actuator潜在的OOM问题,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!此问题背景产生于近期需要上线的一个功能的埋点;主要表现就是在应用启动之后的一段时间...
    99+
    2023-06-21
  • sql模式设置引起的问题解决办法
    目录1 报错类似如下2 解决办法2.1 查看全局sql模式2.2 设置全局sql模式2.3 查看当前sql模式2.4 设置当前sql模式3 永久生效的解决办法3.1 找到my.cnf...
    99+
    2024-04-02
  • sql模式设置引起的问题怎么解决
    今天小编给大家分享一下sql模式设置引起的问题怎么解决的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。1 报错类似如下数据库错...
    99+
    2023-06-30
  • mysql autocommit=0引起的业务hang住问题分析
    这篇文章主要讲解了“mysql autocommit=0引起的业务hang住问题分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“mysql autocom...
    99+
    2024-04-02
  • Go语言中nil判断引起的问题详析
    前言 代码封装是百干不厌的事,但有时候封装会导致一些问题。本文记录了个人在封装 http 请求时遇到的一个和 nil 判断有关的问题。 nil 是什么 在 Go 语言中,布尔类型的...
    99+
    2024-04-02
  • html中浮动元素引起的问题有哪些
    这篇文章主要介绍html中浮动元素引起的问题有哪些,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!一、问题多个浮动的元素无法撑开父元素的宽度,父元素的高度可能会变成0。若浮动元素后面跟非浮动元素,非浮动元素会紧随其后浮...
    99+
    2023-06-08
  • Mybatis整合Spring 由于版本引起的BUG问题
    错误信息:org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [SpringMVC] in context with path...
    99+
    2023-05-31
    mybatis 整合 spring
  • docker引起服务器磁盘爆满的问题解决
    目录服务器异常检查服务器发现异常解决问题服务器异常 又是开开心心打开我心爱的服务器一天;吔!这是嘛啊?我的服务器域名访问不了了,一直转圈圈超时了,好,打开ssh远程看看,吔!!!还是...
    99+
    2024-04-02
  • ios开发try-catch引起的野指针问题排查
    目录1、野指针问题2、崩溃栈3、场景复现代码4、问题分析5、上报可能引起野指针崩溃栈1、野指针问题 【EXC_BAD_ACCESS (SIGSEGV) / KERN_INVALID_...
    99+
    2024-04-02
  • Java代码引起的NATIVE野指针问题怎么解决
    Java代码引起的NATIVE野指针问题怎么解决,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。实施hook:我们有了hook,但目前还不知道是哪个so中释放了f...
    99+
    2023-06-17
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作