近期项目做得差点儿相同了,測试出现了一些问题,当中一个就是内存溢出问题,在三星手机上測试最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防止内存溢出浅析的更多相关文章

  1. Android开发 |常见的内存泄漏问题及解决办法

    在Android开发中,内存泄漏是比较常见的问题,有过一些Android编程经历的童鞋应该都遇到过,但为什么会出现内存泄漏呢?内存泄漏又有什么影响呢? 在Android程序开发中,当一个对象已经不需要 ...

  2. android加载大量图片内存溢出的三种方法

    android加载大量图片内存溢出的三种解决办法 方法一:  在从网络或本地加载图片的时候,只加载缩略图. /** * 按照路径加载图片 * @param path 图片资源的存放路径 * @para ...

  3. Android使用帧动画内存溢出解决方法

    Android使用帧动画内存溢出解决方法https://blog.csdn.net/daitu_liang/article/details/52336015https://blog.csdn.net/ ...

  4. Android开发——Android多进程以及使用场景介绍

    个层级,具体可以查看Android开发--Android进程保活招式大全中1.1部分的内容,这里就不赘述了. 根据进程中当前活动组件的重要程度,Android 会将进程评定为它可能达到的最高级别.例如 ...

  5. Android开发-Android Studio问题以及解决记录

    [Android开发] Android Studio问题以及解决记录   http://blog.csdn.net/niubitianping/article/details/51400721 1.真 ...

  6. Android开发——Android M(6.0) 权限解决方案

    Android开发--Android M(6.0) 权限解决方案 自从Android M(6.0)发布以来,权限管理相比以前有了很大的改变,很多程序员发现之前运行的好好的Android应用在Andro ...

  7. android防止内存溢出浅析

    Android的虚拟机是基于寄存器的Dalvik,它的最大堆大小一般是16M.但是Android采用的是Java语言编写,所以在很大程度上,Android的内存机制等同于Java的内存机制,在刚开始开 ...

  8. android 开发如何做内存优化

    不少人认为JAVA程序,因为有垃圾回收机制,应该没有内存泄露.其实如果我 们一个程序中,已经不再使用某个对象,但是因为仍然有引用指向它,垃圾回收器就无法回收它,当然该对象占用的内存就无法被使用,这就造 ...

  9. Android开发——常见的内存泄漏以及解决方案(二)

    )Android2.3以后,SoftReference不再可靠.垃圾回收期更容易回收它,不再是内存不足时才回收软引用.那么缓存机制便失去了意义.Google官方建议使用LruCache作为缓存的集合类 ...

随机推荐

  1. DuiLib消息处理剖析

    本来想自己写写duilib的消息机制来帮助duilib的新手朋友,不过今天发现已经有人写过了,而且写得很不错,把duilib的主干消息机制都说明了,我就直接转载过来了,原地址:http://blog. ...

  2. C++ 中类的构造函数理解(二)

    C++ 中类的构造函数理解(二) 写在前面 上次的笔记中简要的探索了一下C++中类的构造函数的一些特性,这篇笔记将做进一步的探索.主要是复制构造函数的使用. 复制构造函数 复制构造函数也称拷贝构造函数 ...

  3. 2014 IGF 评选(转)

    前两天受邀去上海参加今年的独立游戏节评选,准确说是亚洲及太平洋地区的 IGF . 居然有接近 400 个参选游戏是让我事前没有想到的,尤其是在学生组还发现了不少好作品是个惊喜. 评审用了整整两天时间, ...

  4. linux 学习网站

    study-Area:http://www.study-area.org 鸟哥的私房菜:http://linux.vbird.org 鸟哥的私房菜课后答案:http://wapwenku.baidu. ...

  5. 说说Python 中的文件操作 和 目录操作

    我们知道,文件名.目录名和链接名都是用一个字符串作为其标识符的,但是给我们一个标识符,我们该如何确定它所指的到底是常规文件文件名.目录名还是链接名呢?这时,我们可以使用os.path模块提供的isfi ...

  6. manacher算法_求最长回文子串长度

    很好的总结,转自: http://blog.csdn.net/dyx404514/article/details/42061017 总结为:两大情况,三小情况. 两大情况:I. i <= p 1 ...

  7. Android之操作SQLite

    一.SQLite的介绍 1.SQLite简介 SQLite是一款轻型的数据库,是遵守ACID的关联式数据库管理系统,它的设计目标是嵌入  式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的 ...

  8. C++中cin、cin.get()、cin.getline()、getline()、gets()等函数的用法----细节决定成败 (sort用法)

    C++中cin.cin.get().cin.getline().getline().gets()等函数的用法 学C++的时候,这几个输入函数弄的有点迷糊:这里做个小结,为了自己复习,也希望对后来者能有 ...

  9. .NET异步编程初识async与await

    这是两个关键字,用于异步编程.我们传统的异步编程方式一般是Thread.ThreadPool.BeginXXX.EndXXX等等.把调用.回调分开来,代码的逻辑是有跳跃的,于是会导致思路不是很清晰的问 ...

  10. effective c++:private继承

    如果class间使用private继承关系,编译器就不会自动的将派生类转换为基类,而且private继承而来的成员都变为private属性. private继承意味着根据某物实现出,当我们想要避免重复 ...