【android开发】Android防止内存溢出浅析

【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机制差,并且更好的控制内存,能使我们的手机执行得更流畅。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/119110.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • js中判断对象是否为空

    js中判断对象是否为空1.es6中可以使用Object.keys(obj)vardata={};vararr=Object.keys(data);alert(arr.length==0);//true为空,false不为空2.将json对象转化为json字符串,再判断该字符串是否为"{}"vardata={};varb=(JSON.stringify(data)==…

    2022年6月14日
    26
  • Flume和Kafka的组合使用

    Flume和Kafka的组合使用在Windows系统中打开第1个cmd窗口,执行如下命令启动Zookeeper服务:cdC:\zookeeper\apache-zookeeper-3.7.1-bin.\bin\zkServer.cmd打开第2个cmd窗口,然后执行下面命令启动Kafka服务:cdC:\kafka_2.12-2.4.0\kafka_2.12-2.4.0.\bin\windows\kafka-server-start.bat.\config\server.properties打开第.

    2022年6月23日
    23
  • 银行风控模型

    银行风控模型风控催生原因对于银行来说,现今互联网贷款和信用卡办理面临的主要难题是数据和风控。站在银行或金融机构角度,自然而然是想获得更多的信息和数据,但是在收集数据这方面又是比较无力的。加上当下的发展趋势,消费贷以及贷款审批速度都要求快。如何在快的的过程中对客户进行一个全面的审查,得出一个合理的结果呢?如果没有详细的数据对客户进行评估,这势必会提高放贷的风险。风控概述所谓风控,是指多银行贷款资金的…

    2022年6月13日
    40
  • python检查文件更新失败_恢复自动更新/更新失败解决方法个人汇总[通俗易懂]

    python检查文件更新失败_恢复自动更新/更新失败解决方法个人汇总[通俗易懂]步骤一:服务开启首先,打开任务管理器(快捷键Ctrl+shift+esc)(或者右键开始图标任务管理器(此方法只适应Win8Win10))(或者Ctrl+Alt+Del,点击任务管理器)打开服务选项卡+打开服务找到windowsupdate,右键,属性启动类型改为手动如果要关闭更新请改为禁用步骤二:组策略开启windows微标键+R键呼出【运行】2输入【gpedit.msc】组策略编辑器计算机配…

    2022年5月16日
    35
  • mybatisPlus填坑之逻辑删除

    mybatisPlus填坑之逻辑删除网上大部分的关于mybatisPlus的逻辑删除的配置介绍都是有问题的,原因可能是官网已经做了更新!!!错误如图:正确的配置是:SpringBoot配置方式: application.yml加入配置(如果你的默认值和mp默认的一样,该配置可无): yml文件(区别是多了一个路径db-config,同学们细看了) mybatis-plus:global-c…

    2022年5月5日
    168
  • 圆柱体积怎么算立方公式_立方计算公式,圆形怎么算立方。[通俗易懂]

    展开全部长方体的立方即是体积:长×宽×高正方体的立方即使体积:棱长x棱长x棱长圆形没e69da5e6ba9062616964757a686964616f31333431363537有立方。常用单位1、立方米、立方分米、立方厘米、立方毫米2、棱长是1毫米的正方体,体积是1立方毫米3、棱长是1厘米的正方体,体积是1立方厘米4、棱长是1分米的正方体,体积是1立方分米5、棱长是1米的正方体,体积是1立方米…

    2022年4月5日
    192

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号