导航:首页 > 操作系统 > 如何避免oomAndroid

如何避免oomAndroid

发布时间:2022-11-27 16:35:58

android中怎么防止oom

内存泄露的原因:
1. Handler造成内存泄漏

private Handler handler = new Handler(){
@Override
public void handMessage(Message msg){

}
}
当使用内部类(包括匿名类)来创建Handler时,Handler对象会隐式地持有一个外部类对象(通常是一个Activity)的引用。
而Handler通常会伴随一个耗时的后台线程(例如访问网络或者从网络上拉取图片)一起出现,这个后台线程在任务执行完毕(例如图片下载完成)之后,通过消息机制通知Handler,然后Handler把图片更新到界面上(主线程中)。
当用户在网络请求过程中关闭了Activity,正常情况下,Activity不再被使用,它就有可能在GC检查时被回收掉。但是由于这时线程尚未执行完,而该线程持有Handler的引用,Handler持有Activity的引用,就导致Activity无法被回收(即内存泄露),直到网络请求结束(例如图片下载完成)。
另外,如果你执行了Handler的postDelayed()方法,该方法会将你的Handler装入一个Message,并把这条Message推到MessageQueue中,那么在你设定的delay到达之前,会有一条MessageQueue —> Message —> Handler —> Activity的链,导致你的Activity被持有引用而无法被回收。
使用Handler导致内存泄露的解决办法:
一、通过程序逻辑进行保护
A. 在finish Activity的时候停掉你的后台线程,线程停掉了,就相当于切断了Handler与外部连接的线,Activity自然会在合适的时候被回收。
B. 如果Handler被delay的Message持有了引用,那么使用相应的Handler的removeCallbacks()方法,把消息对象从消息队列中移除即可。
二、将Handler声明为静态类
静态类不持有外部类的引用对象,所以Activity可以随意被回收。
static class MyHandler extends Handler{

@Override
public void handleMessage(Message msg){
}
}
此时由于Handler不再持有外部类对象的引用,导致程序不允许你在Handler中操作Activity中的对象。所以你需要在Handler中增加一个对Activity的弱引用(WeakReference)
static class MyHandler extends Handler{
WeakReference<Activity> activityReference;
public MyHandler(Activity activity){
activityReference = new WeakReference<Activity>(activity);
}

@Override
public void handleMessage(Message msg){
final Activity activity = activityReference.get();
}
}
对应以上的代码,用户在关闭Activity之后,就算后台线程还没结束,但由于仅有一条来自Handler的弱引用指向Activity,所以GC仍然会在检查的时候把Activity回收掉。
So, 关于Handler内存泄露的问题就不会出现。

② android何时会发生oom怎么解决oom

首先,OOM就是内存溢出,即Out Of Memory。也就是说内存占有量超过了VM所分配的最大。
怎么解决OOM,通常OOM都发生在需要用到大量内存的情况下(创建或解析Bitmap,分配特大的数组等),在这样的一种情况下,就可能出现OOM,据我现在了解到,多数OOM都是因为Bitmap太大。所以,这里我就专门针对如何解决Bitmap的OOM。其实最核发的就是只加载可见范围内的Bitmap,试想这样一种情况,在GridView或ListView中,数据量有5000,每一屏只显示20个元素,那么不可见的,我们是不需要保存Bitmap在内在中的。所以我们就是只把那么可见的Bitmap保留在内存中,那些不可见的,就释放掉。当元素滑出来时,再去加载Bitmap。
这里我有两种方式,都可以避免OOM。

③ oom如何解决和预防

尽量提高自己的免疫力,然后不断的锻炼身体,这样的话对于预防来说是有很好的疗效。
但是我们还需要掌握一定的方式方法。

④ 怎么解决oom android

如果是第一次创建的时候就出错,那试试在创建bitmap的时候不要把public static Bitmap createBitmap (int width, int height, Bitmap.Config config)的第三个参数写成ARGB_8888,换成其他的值。

如果是多次创建的时候才OOM,那么一定要想办法,在合适的地方,对你已经创建的bitmap进行recycle操作。

⑤ android使用全局的dialogview怎样避免oom

避免OOM的第一步就是要尽量减少新分配出来的对象占用内存的大小,尽量使用更加轻量的对象。
1)使用更加轻量的数据结构
1、考虑使用ArrayMap/SparseArray(SparseBoolMap,SparseIntMap,SparseLongMap,LongSparseMap)而不是HashMap等传统数据结构
ArrayMap、SparseArray使用场景:
对象个数的数量级最好是千以内
数据组织形式包含Map结构

⑥ android oom问题 如何避免

ROM有什么问题,你是否能说一下,如果你说的是有些人不断地刷ROM,那不过是他们的兴趣罢了,没有最好的ROM,而那些刷机不断地人则是在找更好的ROM,你如果觉得你的ROM可以忍受,你就不用刷,如果你想试一试新的系统,你就可以刷一下不同的ROM,其实ROM对手机的性能影响还是挺大的,一个好的ROM可以使你的手机更省电,CPU主频更高,你要不要刷,自己看着办把。
说了这么多,我都觉得自己说的挺乱的,如果你有什么问题,接着问吧

⑦ android图片压缩避免OOM

简单吹下牛:很多app都会要加载图片,但是如果不压缩图片就很容易OOM,

个人看来OOM 出现原因总的来说分为两种:

一种是内存溢出(好像在扯淡,OOM本身就是内存溢出)

另一种是:图片过大,一个屏幕显示不完全造成,似乎也是一。。 如有错误纯属扯淡;

为了避免上面的情况:加载图片的时候可以进行压缩,上传的时候要可以进行压缩,在图片不可见的时候进行回收(onDetach()),再吹一句 用了fresco+压缩之后加载图片完全没问题了。

一、质量压缩方法:

privateBitmap compressImage(Bitmap image) {

ByteArrayOutputStream baos =newByteArrayOutputStream();

image.compress(Bitmap.CompressFormat.JPEG,100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中

intoptions =100;

while( baos.toByteArray().length /1024>100) {//循环判断如果压缩后图片是否大于100kb,大于继续压缩

baos.reset();//重置baos即清空baos

image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中

options -=10;//每次都减少10

}

ByteArrayInputStream isBm =newByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中

Bitmap bitmap = BitmapFactory.decodeStream(isBm,null,null);//把ByteArrayInputStream数据生成图片

returnbitmap;

}

二、图片按比例大小压缩方法(根据Bitmap图片压缩)

privateBitmap comp(Bitmap image) {

ByteArrayOutputStream baos =newByteArrayOutputStream();

image.compress(Bitmap.CompressFormat.JPEG,100, baos);

if( baos.toByteArray().length /1024>1024) {//判断如果图片大于1M,进行压缩避免在生成图片(BitmapFactory.decodeStream)时溢出

baos.reset();//重置baos即清空baos

image.compress(Bitmap.CompressFormat.JPEG,50, baos);//这里压缩50%,把压缩后的数据存放到baos中

}

ByteArrayInputStream isBm =newByteArrayInputStream(baos.toByteArray());

BitmapFactory.Options newOpts =newBitmapFactory.Options();

//开始读入图片,此时把options.inJustDecodeBounds 设回true了

newOpts.inJustDecodeBounds =true;

Bitmap bitmap = BitmapFactory.decodeStream(isBm,null, newOpts);

newOpts.inJustDecodeBounds =false;

intw = newOpts.outWidth;

inth = newOpts.outHeight;

//现在主流手机比较多是800*480分辨率,所以高和宽我们设置为

floathh = 800f;//这里设置高度为800f

floatww = 480f;//这里设置宽度为480f

//缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可

intbe =1;//be=1表示不缩放

if(w > h && w > ww) {//如果宽度大的话根据宽度固定大小缩放

be = (int) (newOpts.outWidth / ww);

}elseif(w < h && h > hh) {//如果高度高的话根据宽度固定大小缩放

be = (int) (newOpts.outHeight / hh);

}

if(be <=0)

be =1;

newOpts.inSampleSize = be;//设置缩放比例

//重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了

isBm =newByteArrayInputStream(baos.toByteArray());

bitmap = BitmapFactory.decodeStream(isBm,null, newOpts);

returncompressImage(bitmap);//压缩好比例大小后再进行质量压缩

}

⑧ android开发内存优化之如何有效避免oom

  1. 减小对象的内存占用

  2. 内存对象的重复利用

  3. 避免对象的内存泄露

  4. 内存使用策略优化

⑨ Android Bitmap 内存以及OOM问题讨论

都知道在Android中, 每个应用所使用的内存是有限的,现在的手机通常最大的内存使用为256M, 目前还没发现Android中一个应用的最大内存分配超过256M的(经测试华为手机的最大内存是385M)

相关API:

ActivityManager.getMemoryClass(),首先获取系统服务中的ActivityManager

如下:

(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);

可以获取到相关信息

最近一直被项目的OOM问题困扰, 在网上查阅相关资料,前前后后读了不下于30篇,这些篇幅讲解的东西都是千篇一律,并没有解决到实际问题

也在慕课网学习了内存优化章节

这是慕课网讲师的PPT,我截屏的

这里来仔细分析一下:

第一个,  注意临时Bitmap对象的及时回收, 来看下相关API

直接上图

经过我无数次的使用Android studio工具自带的MAT分析工具后, 得出一个很严谨的结论, 此方法并不奏效...

Android中Bitmap的内存存放在堆区, Google 的Bitmap的recycle方法注释也可以了解到

Android历史版本不是很清楚, 据说Android3.0之前Bitmap是存放在native区域,可以进行手动释放,然而3.0之后Bitmap是存放在Java层的堆区,没错是heap, 内存管理直接交由系统GC管理,你还这样释放资源有意义?无非是给自己的一点心理安慰罢了, 告诉你没卵用

又有人在说要释放内存使用System.gc() ???  对就是主动触发垃圾回收,这个API是开发者自行调用的吗?那么系统管理内存还有什么意义?这不是误人子弟吗,这个API不能调用的, 因为没卵用的, 具体自己参照MAT工具自行分析.即便垃圾回收真的被触发了, 所有线程停滞由系统来清理垃圾, 造成的后果是严重卡顿!!!

再看一个API:

我在网上苦苦追寻内存过高的问题后,发现了这个API,经过无数次实践后我得出一个结论,没卵用...开发者可以抛弃它

综上所诉, 第一点讲解的内存优化问题可以直接PASS掉, 无非给自己一点心理安慰: 我已经处理好了内存问题, 程序不会OOM?

第二点. 避免Bitmap的浪费

直接说结论, 这个是非常行之有效的,并且是一定能解决问题的

具体怎么操作呢? 自己实现LruCache这个类, 就是这么弄, 原理就是解码复用, 在内存中已经解码好的Bitmap直接拿出来使用, 没有的在加载到内存进行解析, 这个非常有效,但是并不能让你避免OOM

第三点, try-catch某些大内存分配的操作

这点上,我又要开始疑问了, 我Java功底不是很好

Java中发生内存溢出时,抛出的是OutOfMemoryError, 它的父类是VirtualMachineError

这玩意能catch住? 它属于Error范畴, 你能捕获?请Java大神出来说一下,我解释不清楚

第四点, 加载Bitmap 缩放比例, 解码格式, 局部加载

先来分析一下缩放比例:

按照市面上主流的手机分辨率来分析现在Android主流的分辨率是1920X1080, 如果一个ImageView控件刚好就是屏幕全屏,怎么说?直接占用掉8M内存, 想想一个实际的需求情况

一个查看大图的页面, 不断的关闭,打开查看新的大图,问题就来了,内存一直在暴增,迟早会突破界限OOM掉

分辨率是2K屏呢? 更恐怖了, 随着手机设备的屏幕分辨率提升, 加载图像需要的内存也是倍增的, 因为应用的最大内存并没有增加

结论: 缩放比例可以有效的降低内存占用问题, 但不是绝对的救命稻草, 该缩放的还是要缩放,而且必须缩放,就是采样  现在通常都是图片加载框架来完成,类似Glide.Picasso,Fresco等,他们可以帮助你减少工作量, 内存问题还是存在

再来分析一下解码格式:

这个跟缩放比例效果差不多, 只是同样的分辨率的图片加载到内存中时占用内存减少了

比如ARGB_8888 共32位

RGB_565  共16位

ARGB_4444 共16位

很明显这样格式图片加载的内存情况是ARGB_8888是其他格式的两倍内存

另外的问题是ARGB_8888看起来很清晰的, 其它的看起来图片有种糊了的感觉,自己选择吧

结论, 降低内存占用非常有效

最后一个是局部加载, 并没有怎么使用到,也不清楚就不说了

最后还有一个方法避免OOM, 开启largeHeap属性, 但是但是, 以前我们开启这个属性后被Oppo应用市场认定为占用内存过高, 不建议用户安装......所以我们又取消了!

总的来说, Bitmap在内存是变现的是不可控, 我项目OOM问题一直没有得到有效解决,因为图片编辑视频编辑之类的功能占用内存过高,继续使用OOM是必然的, 跟IOS的同学交流了一番,他们说IOS的应用内存可以占用到1个G以上, 轻松跑到500M是没问题的, IOS的内存机制可以持续给内存使用, 具体我也不清楚,并且他们可以手动释放内存?malloc, free这样子?

如果大家有比较好的方案,还望留言交流互相帮助 [笑脸.gif]

补充: Android8.0开始Bitmap数据内存存在native层, 单个应用可用的内存显着增长, 极大的降低了OOM的概率(2018年3月22日)

阅读全文

与如何避免oomAndroid相关的资料

热点内容
世界上最简单的解压神器 浏览:566
一人之下小说txt全文 浏览:584
.超大尺度男男电影 浏览:396
无法找到加密狗将进入演示模式 浏览:134
韩国李彩谭主演的电影 浏览:560
redisphp管理 浏览:958
被人切掉蛋蛋电影 浏览:894
美国最新女机器人电影 浏览:22
万达电影院用英语怎么说 浏览:123
伊朗人购买加密货币 浏览:373
杭州哪儿找程序员 浏览:268
警察卧底监狱韩国电影叫什么电影 浏览:607
app激活小米移动网络连接到服务器地址 浏览:84
决策树归纳算法 浏览:873
欧美以小孩为主角的电影 浏览:432
肉写得好的古言作者 浏览:187
韩国电影失踪国语在线观看 浏览:39
盗墓电影免费大全 浏览:177
内地大尺度电影 浏览:297
日历女孩女二的扮演者李熙3围 浏览:220