【android开发】Android防止内存溢出浅析
近期项目做得差点儿相同了,測试出现了一些问题,当中一个就是内存溢出问题,在三星手机上測试最easy出现内存溢出,在其它手机上,比方华为就没有发生,也是比較郁闷。这个问题在之前的公司,做项目时也遇到过,非常大一方面是自己写的代码问题,今天在网上找了一些知识,给大家分享一下:
Android的虚拟机是基于寄存器的Dalvik,它的最大堆大小通常是16M。可是Android採用的是Java语言编写,所以在非常大程度上,Android的内存机制等同于Java的内存机制,在刚開始开发的时候,内存的限制问题会给我们带来内存溢出等严重问题。在我们不使用一些内存的时候,我们要尽量在Android或者其它平台上避免在执行其它程序时,保存必要的状态,使得一些死进程所带来的内存问题,应该尽量在关闭程序或者保存状态的时候释放掉,这样能提高系统在执行方面的流畅性。
Android的内存主要表如今:
1. 在Android平台上,长期保持一些资源的引用,造成一些内存不能释放,带来的内存泄露问题非常多。比方:Context(下文中提到的Activity都是Context),在一些你须要保持你的首个类对象状态,而且把状态传入其它类对象中时,这样消除掉首个类对象之前,你必须先把接收类对象释放掉。须要注意一点的是:由于在Java或者Android内存机制中,顶点的结点释放前必须保证其它对象没有调用才干被系统GC回收释放。我们来看一段代码:
@Override
protected void onCreate(Bundle state) {
super.onCreate(state);
TextViewlabel = new TextView(this);
label.setText("Leaksare bad");
setContentView(label);
}
这个代码的意思就是我们把一个TextView的实例载入到了我们正在执行的Activity(Context)其中,因此,通过GC回收机制,我们知道,要释放Context,就必须先释放掉引用他的一些对象。假设没有,那在要释放Context的时候,你会发现会有大量的内存溢出。所以在你不小心的情况下内存溢出是一件很easy的事情。 保存一些对象时,同一时候也会造成内存泄露。最简单的比方说位图(Bitmap),比方说:在屏幕旋转时,会破坏当前保持的一个Activity状态,而且又一次申请生成新的Activity,直到新的Activity状态被保存。我们再看一段代码:
privatestatic Drawable sBackground;
@Override
protected void onCreate(Bundle state) {
super.onCreate(state);
TextView label = new TextView(this);
label.setText("Leaks are bad"); if (sBackground == null) {
sBackground =getDrawable(R.drawable.large_bitmap);
}
label.setBackgroundDrawable(sBackground);
setContentView(label);
}
这个代码是非常快的同一时候也是错误的。它的内存泄露非常easy出在屏幕转移的方向上。尽管我们会发现没有显示的保存Context这个实例,可是当我们把绘制的图连接到一个视图的时候,Drawable就会将被View设置为回调,这就说明,在上述的代码中,事实上在绘制TextView到活动中的时候,我们已经引用到了这个Activity。链接情况能够表现为:Drawable->TextView->Context。
所以在想要释放Context的时候,事实上还是保存在内存中,并没有得到释放。
怎样避免这样的情况:主要在于。线程最easy出错。大家不要小看线程,在Android里面线程最easy造成内存泄露。线程产生内存泄露的主要原因在于线程生命周期的不可控。以下有一段代码:
publicclass MyTest extends Activity {
@Override
publicvoid onCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new MyThread().start();
}
privateclass MyThread extends Thread{
@Override
public void run() {
super.run();
//do somthing
}
}
}
代码非常easy,可是在Android上又来新问题了,当我们在切换视图屏幕的时候(横竖屏),就会又一次建立横屏或者竖屏的Activity。我们形象的觉得之前建立的Activity会被回收,可是事实怎样呢?Java机制不会给你相同的感受,在我们释放Activity之前,由于run函数没有结束,这样MyThread并没有销毁,因此引用它的Activity(Mytest)也有没有被销毁,因此也带来的内存泄露问题。
有些人喜欢用Android提供的AsyncTask,但其实AsyncTask的问题更加严重,Thread仅仅有在run函数不结束时才出现这样的内存泄露问题,然而AsyncTask内部的实现机制是运用了ThreadPoolExcutor,该类产生的Thread对象的生命周期是不确定的,是应用程序无法控制的,因此假设AsyncTask作为Activity的内部类,就更easy出现内存泄露的问题。
线程问题的改进方式主要有:
l 将线程的内部类,改为静态内部类。
l 在程序中尽量採用弱引用保存Context。
2. 万恶的bitmap。。。
Bitmap是一个非常万恶的对象,对于一个内存对象,假设该对象所占内存过大,在超出了系统的内存限制时候,内存泄露问题就非常明显了。。
解决bitmap主要是要解决在内存尽量不保存它或者使得採样率变小。在非常多场合下,由于我们的图片像素非常高,而对于手机屏幕尺寸来说我们并不用那么高像素比例的图片来载入时,我们就能够先把图片的採样率减少在做原来的UI操作。
假设在我们不须要保存bitmap对象的引用时候,我们还能够用软引用来做替换。详细的实例代码google上面也有非常多。
综上所述,要避免内存泄露,主要要遵循下面几点:
第一:不要为Context长期保存引用(要引用Context就要使得引用对象和它本身的生命周期保持一致)。
第二:假设要使用到Context,尽量使用ApplicationContext去取代Context,由于ApplicationContext的生命周期较长,引用情况下不会造成内存泄露问题
第三:在你不控制对象的生命周期的情况下避免在你的Activity中使用static变量。尽量使用WeakReference去取代一个static。
第四:垃圾回收器并不保证能准确回收内存,这样在使用自己须要的内容时,主要生命周期和及时释放掉不须要的对象。尽量在Activity的生命周期结束时,在onDestroy中把我们做引用的其它对象做释放,比方:cursor.close()。
事实上我们能够在非常多方面使用更少的代码去完毕程序。比方:我们能够多的使用9patch图片等。有非常多细节地方都能够值得我们去发现、挖掘很多其它的内存问题。我们要是能做到C/C++对于程序的“谁创建,谁释放”原则,那我们对于内存的把握,并不比Java或Android本身的GC机制差,并且更好的控制内存,能使我们的手机执行得更流畅。
【android开发】Android防止内存溢出浅析的更多相关文章
- Android开发 |常见的内存泄漏问题及解决办法
在Android开发中,内存泄漏是比较常见的问题,有过一些Android编程经历的童鞋应该都遇到过,但为什么会出现内存泄漏呢?内存泄漏又有什么影响呢? 在Android程序开发中,当一个对象已经不需要 ...
- android加载大量图片内存溢出的三种方法
android加载大量图片内存溢出的三种解决办法 方法一: 在从网络或本地加载图片的时候,只加载缩略图. /** * 按照路径加载图片 * @param path 图片资源的存放路径 * @para ...
- Android使用帧动画内存溢出解决方法
Android使用帧动画内存溢出解决方法https://blog.csdn.net/daitu_liang/article/details/52336015https://blog.csdn.net/ ...
- Android开发——Android多进程以及使用场景介绍
个层级,具体可以查看Android开发--Android进程保活招式大全中1.1部分的内容,这里就不赘述了. 根据进程中当前活动组件的重要程度,Android 会将进程评定为它可能达到的最高级别.例如 ...
- Android开发-Android Studio问题以及解决记录
[Android开发] Android Studio问题以及解决记录 http://blog.csdn.net/niubitianping/article/details/51400721 1.真 ...
- Android开发——Android M(6.0) 权限解决方案
Android开发--Android M(6.0) 权限解决方案 自从Android M(6.0)发布以来,权限管理相比以前有了很大的改变,很多程序员发现之前运行的好好的Android应用在Andro ...
- android防止内存溢出浅析
Android的虚拟机是基于寄存器的Dalvik,它的最大堆大小一般是16M.但是Android采用的是Java语言编写,所以在很大程度上,Android的内存机制等同于Java的内存机制,在刚开始开 ...
- android 开发如何做内存优化
不少人认为JAVA程序,因为有垃圾回收机制,应该没有内存泄露.其实如果我 们一个程序中,已经不再使用某个对象,但是因为仍然有引用指向它,垃圾回收器就无法回收它,当然该对象占用的内存就无法被使用,这就造 ...
- Android开发——常见的内存泄漏以及解决方案(二)
)Android2.3以后,SoftReference不再可靠.垃圾回收期更容易回收它,不再是内存不足时才回收软引用.那么缓存机制便失去了意义.Google官方建议使用LruCache作为缓存的集合类 ...
随机推荐
- 上传Test Result和attachment到ALM
之前在HP的时候用ALM,还是很好用的功能很强大的一个测试管理工具,当时用C#依照ALM的API实现了一个上传测试结果的程序,现在贴出来: 这个程序的使用方式很自由,使得ALM几乎可以和所有测试工具做 ...
- (转) SQL 命令
省的自己总结了 1.终端启动MySQL:/etc/init.d/mysql start:(stop ,restart.)2.登录MySQL:mysql -uroot -p (用root账户登录),然后 ...
- .net core 使用
在本机上安装了 visual studio 2015后,还要安装 DotNetCore.1.0.1-VS2015Tools.Preview2.0.3.exe 才能编译 .net core 的代码.不然 ...
- vim中编码方式---不完整总结
关于编码,总有很多故事,这里只是记录下暂时的东西. 1.关于查看文件的编码 在查看文件编码的时候,总是倾向于使用file来进行查看,然而使用file命令的时候,并没有什么卵用: 在查看细节的时候,可以 ...
- Android中的颜色值RGB对照表表
Android中颜色值是通过红(Red).绿(Green).蓝 (Blue)三原色,以及一个透明度(Alpha)值来表示的,颜色值总是以井号(#)开头,接下来就是Alpha-Red-Green-Blu ...
- python异常以及面向对象编程
一.面向对象 需要注意的是,在Python中,变量名类似__xxx__的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是private变量,所以,不能用__na ...
- CUDA ---- Hello World From GPU
本篇博文仅实现hello world,先看到效果,具体细节将在后续博文解释. 准备 如果你是第一次使用CUDA,在Linux下可以使用下面的命令来检查CUDA编译器是否安装正确: $ which nv ...
- 想要完全导入swc中的所有类
其实还有个这个办法.修改参数.-include-libraries library [...] 强制导入SWC文件中的所有类,不管是否曾使用过这个类 (((比如把swc文件放到src里,然后编译参数加 ...
- Office 365 plans, SharePoint Online, and SharePoint 2013 on-premises 功能对比列表
Andrew ConnellSharePoint大牛整理了一个各个版本SharePoint功能对比列表,是SharePoint相关人员必备资料.赶紧收藏起来. SharePoint 2013 Feat ...
- 邮件发送服务AWS SES,Mailgun以及SendCloud(转)
原文:http://www.l4zy.com/posts/aws_ses-mailgun-sendcloud.html 电子邮件这一已经诞生很多年的互联网基础服务并没有随着时间的推移而慢慢消亡,实际上 ...