真正能避开内存泄漏与溢出的,是写代码时就具备内存意识的人:缩小变量作用域、慎用静态引用、及时释放资源、合理管理集合与异步任务生命周期。

面试中常被问到内存泄漏与溢出问题,不是考你背概念,而是看你日常编码有没有“内存意识”。真正能避开这些问题的,往往不是最懂JVM参数的人,而是写代码时就主动防患的人。
变量作用域越小越好
局部变量用完即弃,成员变量慎用静态引用。比如在Activity或Fragment里直接持有一个Context的静态引用,Activity销毁后仍被持有,就会泄漏。
- 非必要不声明static修饰的对象,尤其避免static Context、static View、static Handler
- 用WeakReference包装可能长生命周期持有的短生命周期对象(如Activity)
- 在onDestroy()或onDetach()中主动置空监听器、回调、RxJava Disposable等引用
资源用完必须显式释放
流、数据库Cursor、Bitmap、SensorManager、LocationManager、HandlerThread这些都不是“用了就忘”的类型。JVM不会自动帮你关掉它们。
- InputStream/OutputStream、Cursor、SQLiteDatabase务必在finally块或try-with-resources中close()
- 注册的广播接收器、传感器监听器、定位监听器,对应生命周期内unregister/remove
- Handler.postDelayed()的Runnable,若Activity已销毁,记得removeCallbacks()防止空指针+泄漏
集合类别当“无底洞”
ArrayList、HashMap、EventBus、RxBus等容器一旦长期持有对象,又没及时清理,就是典型的内存泄漏温床。
- 缓存集合要设大小上限,或用LruCache替代普通Map
- 用弱引用集合(如WeakHashMap)存储仅需临时关联的对象
- 观察者模式中,注册和反注册必须成对出现;避免在Adapter里保存Activity引用做点击回调
异步任务绑定生命周期
线程、协程、RxJava、AsyncTask这些脱离UI线程运行的任务,很容易在页面销毁后还在更新UI或持有View引用。
- AndroidX推荐使用LifecycleScope.launchWhenStarted/launchWhenResumed,自动取消协程
- RxJava用CompositeDisposable + dispose(),并在onCleared()中统一清空
- 自定义线程池任务完成前先检查isFinishing()或isDestroyed(),避免回调到已销毁页面
内存问题不靠事后排查,靠每行代码的习惯。写完一个功能,顺手问自己一句:这个对象谁来回收?它会不会比我想的活得更久?











