安卓面经_安卓基础面全解析(29/30)之内存优化全解析
牛客高级系列专栏:
- 安卓面经150道高频面试题答案解析专栏链接:Android面试题解析大全
- 安卓面经150道高频面试题答案解析目录详情:安卓面经_Android面经_150道安卓基础面试题目录
- Android进阶知识体系解析专栏链接:Android进阶知识体系解析
- Android进阶知识体系解析目录详情:Android进阶知识体系解析_20大安卓进阶必备知识点
- 安卓系统Framework面经专栏链接:Android系统面试题解析大全
- 安卓系统Framework面经目录详情:Android系统面经_Framework开发面经_130道安卓系统面试题答案解析
- 嵌入式面经111道高频面试题答案汇总专栏链接:嵌入式/C++面试题解析大全
- 嵌入式面经111道高频面试题答案汇总目录详情:111道嵌入式面经题全解析软件开发面经C++面经目录
- 嵌入式项目交流分享链接:嵌入式项目交流分享(附源码)
本人是2020年毕业于广东工业大学研究生:许乔丹,有国内大厂CVTE和世界500强企业安卓开发经验,该专栏整理本人对常见安卓高频开发面试题的理解;
网上安卓资料千千万,笔者将继续维护专栏,一杯奶茶价格不止提供答案解析,承诺提供专栏内容免费技术答疑,直接咨询即可。助您提高安卓面试准备效率,为您面试保驾护航!
正文开始⬇
内存优化是Android开发性能优化最重要的优化点之一。面试中,面试官可能会问你是否有做过内存优化,有的话直接说出实际优化经验即可,如果没有大概率也不会再追问内存优化的理论知识。不过为了能力的提升,本篇一起探索内存优化。面试官可能会问:
- 什么是OOM、内存泄漏、内存抖动?如何发生的? ⭐⭐⭐⭐⭐
- Handler导致的内存泄露你是如何解决的? ⭐⭐⭐⭐
- 知道如何定位内存泄漏吗?有什么工具?⭐⭐⭐⭐
- 请至少例举出5种内存泄漏情况。⭐⭐⭐⭐⭐
- 在 Android 中如何避免内存泄漏?⭐⭐⭐⭐⭐
- 谈谈你项目中内存优化的一些经验(开放题)⭐⭐⭐
看完以下的解析,一定可以让面试官眼前一亮。
目录
- 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
}
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
#提供免费售后答疑!!花一杯奶茶的钱获得安卓面试答疑服务,稳赚不赔# Android发展已经很多年,安卓资料网上千千万,本专栏免费提供专栏内容技术答疑!!私聊当天必回。在阅读过程或者其他安卓学习过程有疑问,都非常欢迎私聊交流。