安卓性能优化之--内存优化

牛客高级系列专栏:

安卓

嵌入式


本人是2020年毕业于广东工业大学研究生:许乔丹,有国内大厂CVTE和世界500强企业安卓开发经验,网上安卓资料千千万,笔者将继续维护专栏,一杯奶茶价格不止提供答案解析,承诺提供专栏内容免费技术答疑,直接咨询即可。助您快速掌握安卓App性能优化技巧!

正文开始⬇

内存优化是Android开发性能优化最重要的优化点之一。面试中,面试官可能会问你是否有做过内存优化,有的话直接说出实际优化经验即可,如果没有大概率也不会再追问内存优化的理论知识。不过为了能力的提升,本篇一起探索内存优化。面试官可能会问:

  1. 什么是OOM、内存泄漏、内存抖动?如何发生的? ⭐⭐⭐⭐⭐
  2. Handler导致的内存泄露你是如何解决的? ⭐⭐⭐⭐
  3. 知道如何定位内存泄漏吗?有什么工具?⭐⭐⭐⭐
  4. 请至少例举出5种内存泄漏情况。⭐⭐⭐⭐⭐
  5. 在 Android 中如何避免内存泄漏?⭐⭐⭐⭐⭐
  6. 谈谈你项目中内存优化的一些经验(开放题)⭐⭐⭐

看完以下的解析,一定可以让面试官眼前一亮。

目录

  • 1、概述
  • 2、引起内存泄漏的场景及解决方法
    • 2.1 Handler 内存泄漏
    • 2.2 非静态内部类的静态实例
    • 2.3 资源性对象
    • 2.4 WebView
    • 2.5 静态变量持有大数据对象
    • 2.6 注册后没有注销
    • 2.7 单例对象
    • 2.8 集合只增不减
    • 2.9 finalize()
    • 2.10 匿名内部类
    • 2.11 图片
  • 3、内存抖动
  • 4、如何减少内存使用
  • 5、内存分析工具和内存分析命令
    • 5.1 内存分析工具
    • 5.2 内存分析命令
  • 6、内存优化总结

1、概述

内存优化的目的是为了避免出现内存泄漏,内存溢出(OOM:Over Of Memory)、内存抖动等问题:

  • 内存泄漏:当一个对象A在程序中已经打算释放了,但有其他对象持有对象A的强引用,导致对象A不能正常被系统回收,继续占用着内存,如此反复使实际可使用内存越来越小。
  • 内存溢出:当内存使用量超过了虚拟机分配给当前程序的最大值时,就会发生内存溢出。出现这种情况很可能是加载的资源太多,如加载大图片,或者分配了很大的数组等变量,或者是太多的内存泄漏最终导致内存溢出;
  • 内存抖动:当内存频繁分配和回收导致内存不稳定,就会出现内存抖动,它通常表现为 频繁GC、内存曲线呈锯齿状;

内存优化的意义:

  • 通过减少OOM,可以提高程序的稳定性;
  • 减少程序的内存占用,提高程序在后台进程的存活率;
  • 减少卡顿,提高程序的流畅度;

本文会先从理论出发,先讨论引起内存异常的各种场景,接着讨论如何避免以及利用工具来分析,优化问题。

2、引起内存泄漏的场景及解决方法

单个的内存泄漏一般不会引起系统异常,但如果众多的内存泄漏则可能导致内存溢出,最后导致系统异常。因此, 一起看看有哪些可能造成内存泄漏的场景。

2.1 Handler 内存泄漏

Handler发出一个消息后,消息会储存在消息队列里,而每个消息都会对应一个目标Handler,也称为target,target是Handler的一个引用。因此如果消息一直存放在消息队列里,将导致Handler无法被回收。

还有另一种情况,因为Handler一般是作为Activity的内部类,可以发送延迟执行的消息,如果在延迟阶段,我们把Activity关掉,此时因为消息队列还有未处理或者正在处理的消息,而消息队列里面的消息又持有Handler实例的引用,同时该Activity还被Handler这个内部类所持有,导致Activity无法被回收,没有真正退出并释放相关资源,最终就造成内存泄漏。

工程上常用的方法是将 Handler 定义成静态的内部类,在内部持有 Activity 的弱引用,并在Acitivity的onDestroy()中调用handler.removeCallbacksAndMessages(null)及时移除所有消息。如果和面试官说了这两个方法,那你就100分过关了,但更进一步是建议将Handler抽离出来作为BaseHandler,然后每个Activity需要用到Handler的时候,就去继承BaseHandler。最佳解决方案具体代码:

// 这个是BaseHandler
public abstract class BaseHandler<T> extends Handler {
    private final WeakReference<T> mWeakReference; //弱引用

    protected BaseHandler(T t) {
        mWeakReference = new WeakReference<T>(t);
    }

    protected abstract void handleMessage(T t, Message msg);

    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        if (mWeakReference == null) {
            return;
        }

        T t = mWeakReference.get();
        if (t != null) {
            handleMessage(t, msg);
        }
    }
}

//然后在某个Activity中使用
 private static class H extends BaseHandler<XuruiActivity> { //静态的内部类哦
       
        public H(XuruiActivity activity) {
            super(activity);
        }

        @Override
        protected void handleMessage(XuruiActivity activity, Message msg) {
            //do something
        }
    }
//同时Activity的onDestroy函数取消掉所有消息
@Override
protected void onDestroy

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

安卓性能优化讲解和实践 文章被收录于专栏

性能优化是高级工程师必备的技能,本专栏将介绍安卓App各种性能优化的方案和实践,让你轻松搞定App性能优化,成为高级工程师,本专栏包括但不限于:启动优化 -&gt; 内存优化 -&gt; 卡顿优化 -&gt; 包体积优化 -&gt; 崩溃优化 -&gt; 耗电优化 -&gt; 布局优化 -&gt; 线程优化 -&gt; 网络优化等。 (目前还在编写阶段,预计2023下半年开始发布)

全部评论

相关推荐

1 2 评论
分享
牛客网
牛客企业服务