A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

四个月的学习马上就要结束了,不得不感叹“时光如梭,白驹过隙”。曾经总是嫌弃漫长,如今却感慨让时间慢一些。每次看阳哥的面试宝典都收货颇多。无论是代码质量还是语言修辞的衔接,恐怕即便是站在巨人的肩膀上,要追上技术牛人的脚步也要付出常人难以接受的努力吧。

对于这篇面试总结,简直喜欢和崇拜的不行。

说了太多的废话,占了几段篇幅,还是直接切入重点吧。

对于性能分析,也经常搜索相关资料,恕我才疏学浅,但还是忍不住发表一下观点。

从内存泄露说起:

先来看看Square公司给出的在Android中内存泄露的解释:

> What is a memory leak?
  Some objects have a limited lifetime. When their job is done, they are expected to be garbage collected. If a chain of references holds an object in memory after the end of its expected lifetime, this creates a memory leak. When these leaks accumulate, the app runs out of memory.
>
  For instance, after Activity.onDestroy() is called, the activity, its view hierarchy and their associated bitmaps should all be garbage collectable. If a thread running in the background holds a reference to the activity, then the corresponding memory cannot be reclaimed. This eventually leads to an OutOfMemoryError crash.

大概翻译就是:  有些对象有一个有限的生命周期,当他们任务结束的时候,应该被GC回收。如果在该对象生命周期结束的时候,仍然有一系列对象hold住了该对象的引用,就会导致内存泄露。随着泄露的积累,app将内存将消耗殆尽。、
比如Activity.onDestroy( )被回调之后,view层级树以及关联的bitmap都应该被GC回收,如果一个正在运行的后台线程hold住了这个activity的引用,与其相关的内存将不会被回收,最终会导致outOfMemoryError崩溃。
从而可见,OOM一般代表着更深层次的问题:Memory Leak

由此可见,内存泄露指的是程序中一些对象不会被GC回收,而始终占用内存,即在对象的引用链中变成了可达不可用。而内存溢出是指程序运行期间无法申请足够的内存而导致的错误,可以说内存泄露是内存溢出的一种诱因,但是不唯一因素。

那么看一下这个著名的诞生于2009年的static Drawable例子,然后在SDK中查看一下历代SDK版本号,会发现

    /**
    * December 2009: Android 2.0.1
    */
     public static final int ECLAIR_0_1 = 6;


    /**
    * January 2010: Android 2.1
    */
    public static final int ECLAIR_MR1 = 7;

2009年的最后一个版本是2.0.1。2.1版本才出现在2010年,而且这个年代,貌似国内做Android的人少之甚少。


所以只需要把这些SDK的版本,翻看一遍,确实会发现这个有内存泄露隐患的强引用链:

Drawable->TextView->Context

但是如果看一下划时代的3.0版本(HONEYCOMB),会发现Google的Android小组貌似已经注意到了这个问题,并且修复了它。
   


     public final void setCallback(Callback cb) {
        mCallback = cb;
    }

替换为

    public final void setCallback(Callback cb) {
        mCallback = new WeakReference<Callback>(cb);
    }

用弱引用来代替强引用,这样就避免了Context的泄露。

再来说说Bitmap.recycle()。

这个也可以算是一个历史遗留问题。在3.0版本之前。

Bitmap.java源码。

    // Note:  mNativeBitmap is used by FaceDetector_jni.cpp
    // Don't change/rename without updating FaceDetector_jni.cpp
    private final int mNativeBitmap;

Bitmap的资源是在底层C中处理的,因此3.0之前的.recycle(),并没有什么错。但是在3.0以及之后。
Bitmap.java源码。

    /**
     * Backing buffer for the Bitmap.
     */
     private byte[] mBuffer;

图片数据保存在成员变量mBuffer中,也就是说使用Heap存储代替了底层C处理。因此不用显式调用.recycle()。只需要把bitmap置null或者使用虚引用持有就行了。这样图片就能被GC回收了。

另外,由于不同版本的SDK,.recycle()注释也不同,但是有一句话是始终没有改变的

>This is an advanced call, and normally need not be called, since the normal GC process will free up this memory when there are no more references to this bitmap.

这是一个高级函数,一般情况下没必要调用,在没有引用指向bitmap时,GC会自动释放内存。


而且我的建议是不要频繁的调用System.gc();因为这在大多情况下只能显式提醒GC回收,究竟什么时候进行回收操作,还是看VM自身的算法和调度。

目前只看到这了,后面如果还有所学以及所想,还会跟阳哥交流的。如果我的理解和建议还算中肯,希望给个置顶。有人看的文,才会有动力继续创作。
回复 使用道具 举报
mark一下,以前只知道java的测试,真不知道安卓的性能优化
回复 使用道具 举报
gawain 中级黑马 2015-11-14 10:04:20
23#
太给力了
回复 使用道具 举报
gawain 中级黑马 2015-11-14 10:08:43
24#
阳哥,这个帖子能提供Download么>

点评

http://bbs.itheima.com/thread-223527-1-1.html  发表于 2015-11-14 15:39
回复 使用道具 举报
感觉好难啊,但是看起来很有意思,以后必须好好学习.
回复 使用道具 举报
加油
回复 使用道具 举报
收藏一下.......
回复 使用道具 举报
支持一下!!!
回复 使用道具 举报
學習到了,感謝分享
回复 使用道具 举报
赞一个!!!
回复 使用道具 举报
赞赞赞赞
回复 使用道具 举报
支持一下!!
回复 使用道具 举报
阳哥,赞一个,坚持更新,加油,果断收藏
回复 使用道具 举报
好东西!!!
回复 使用道具 举报
很实用,顶一个
回复 使用道具 举报
很好的面试资料
回复 使用道具 举报
总结的很好,为什么我怎么不会总结呢?
回复 使用道具 举报
怎么下载不了
回复 使用道具 举报
果维 中级黑马 2015-12-24 10:34:27
39#
顶顶顶顶顶顶顶顶顶顶顶
回复 使用道具 举报
已收藏,留意备用
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马