探索 Android 内存优化方法( 七 )


下面这两张图中 , 第一个是 LeakCanary 为非 AndroidX 项目安装的应用 , 第二个是 LeakCanary 为 AndroidX 项目安装的应用 。

探索 Android 内存优化方法

文章插图
11.4 使用 LeakCanary 分析内存泄漏
下面是一个静态变量持有 Activity 导致 Activity 无法被释放的一个例子 。
publicclassMemoryLeakActivityextendsAppCompatActivity{
publicstaticList<Activity> activities = newArrayList<>;
@Override
protectedvoidonCreate(@Nullable Bundle savedInstanceState){
super.onCreate(savedInstanceState);
activities.add( this);
}
}
我们可以在 Logcat 中看到泄漏实例的引用链 。
探索 Android 内存优化方法

文章插图
除了 Logcat , 我们还可以在 Leaks App 中看到引用链 。
点击桌面上 LeakCanary 为我们安装的 Leaks 应用后 , 可以看到 activities 变量 , 之所以在这里会显示这个变量 , 是因为 LeakCanary 分析的结果是这个变量持有了某个实例 , 导致该实例无法被回收 。
探索 Android 内存优化方法

文章插图
点击这一项泄漏信息 , 我们可以看到一个泄漏信息概览页 。
探索 Android 内存优化方法

文章插图
我们点击第一项 MemoryActivity Leaked , 可以看到泄漏引用链的详情 。
探索 Android 内存优化方法

文章插图
通过上面这些步骤 , 很简单地就能找到 LeakCanary 为我们分析的导致内存泄漏的地方 。
12. 怎么获取和监听系统内存状态?
Android 提供了两种方式让我们可以监听系统内存状态 , 下面我们就来看看这两种方式的用法 。
12.1 ComponentCallback2
在 Android 4.0 后 , Android 应用可以通过在 Activity 中实现 ComponentCallback2 接口获取系统内存的相关事件 , 这样就能在系统内存不足时提前知道这件事 , 提前做出释放内存的操作 , 避免我们自己的应用被系统干掉 。
ComponentCallnback2 提供了 onTrimMemory(level) 回调方法 , 在这个方法里我们可以针对不同的事件做出不同的释放内存操作 。
importandroid.content.ComponentCallbacks2
classMainActivity: AppCompatActivity, ComponentCallbacks2 {
/**
* 当应用处于后台或系统资源紧张时 , 我们可以在这里方法中释放资源 , 
* 避免被系统将我们的应用进行回收
* @paramlevel 内存相关事件
*/
overridefunonTrimMemory(level: Int){
// 根据不同的应用生命周期和系统事件进行不同的操作
when(level) {
// 应用界面处于后台
ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN -> {
// 可以在这里释放 UI 对象
}
// 应用正常运行中 , 不会被杀掉 , 但是系统内存已经有点低了
ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE,
// 应用正常运行中 , 不会被杀掉 , 但是系统内存已经非常低了 , 
// 这时候应该释放一些不必要的资源以提升系统性能
ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW,
// 应用正常运行 , 但是系统内存非常紧张 , 
// 系统已经开始根据 LRU 缓存杀掉了大部分缓存的进程
// 这时候我们要释放所有不必要的资源 , 不然系统可能会继续杀掉所有缓存中的进程
ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL -> {
// 释放资源
}
// 系统内存很低 , 系统准备开始根据 LRU 缓存清理进程 , 
// 这时我们的程序在 LRU 缓存列表的最近位置 , 不太可能被清理掉 , 
// 但是也要去释放一些比较容易恢复的资源 , 让系统内存变得充足
ComponentCallbacks2.TRIM_MEMORY_BACKGROUND,
// 系统内存很低 , 并且我们的应用处于 LRU 列表的中间位置 , 
// 这时候如果还不释放一些不必要资源 , 那么我们的应用可能会被系统干掉
ComponentCallbacks2.TRIM_MEMORY_MODERATE,
// 系统内存非常低 , 并且我们的应用处于 LRU 列表的最边缘位置 , 
// 系统会有限考虑干掉我们的应用 , 如果想活下来 , 就要把所有能释放的资源都释放了
ComponentCallbacks2.TRIM_MEMORY_COMPLETE -> {


推荐阅读