public class TestActivity extends AppCompatActivity {
private static ImageView imageView;
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
imageView = findViewById(R.id.test_img);
imageView.setImageResource(R.drawable.ic_launcher_background);
}
}
上述的代码中的imageView会导致TestActivity无法被GC回收
//------------------------注释1-------------------------------
private Handler handler = new Handler() {
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
}
};
//------------------------注释2-------------------------------
private static class MyHandler extends Handler {
private final WeakReference<TestActivity> mActivity;
public MyHandler(TestActivity activity) {
mActivity = new WeakReference<>(activity);
}
@Override
public void handleMessage(@NonNull Message msg) {
TestActivity testActivity = mActivity.get();
if (testActivity != null) {
// do something
}
}
}
上述代码中注释1是日常开发中写的样子也会造成Activity的内存泄漏,一般需要将其置为static,然后内部持有一个Activity的弱引用来避免内存泄漏。如注释2所示。
三方库初始化的时候一般使用applicationContext作为上下文参数,一般如果我们自己开发相关的SDK的时候一般用context.getApplicationContext() 的方法避免内存泄漏
LeakCanary 中对内存泄漏检测的核心原理就是基于 WeakReference 和 ReferenceQueue 实现的。
当一个 Activity 需要被回收时,就将其包装到一个 WeakReference 中,并且在 WeakReference 的构造器中传入自定义的 ReferenceQueue。
然后给包装后的 WeakReference 做一个标记 Key,并且在一个强引用 Set 中添加相应的 Key 记录
最后主动触发 GC,遍历自定义 ReferenceQueue 中所有的记录,并根据获取的 Reference 对象将 Set 中的记录也删除
经过上面 3 步之后,还保留在 Set 中的就是:应当被 GC 回收,但是实际还保留在内存中的对象,也就是发生泄漏了的对象。
LeakCanary 中监听 Activity 生命周期是由 ActivityRefWatch 来负责的,主要是通过注册 Android 系统提供的 ActivityLifecycleCallbacks,来监听 Activity 的生命周期方法的调用
new Application.ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {
}
@Override
public void onActivityStarted(@NonNull Activity activity) {
}
@Override
public void onActivityResumed(@NonNull Activity activity) {
}
@Override
public void onActivityPaused(@NonNull Activity activity) {
}
@Override
public void onActivityStopped(@NonNull Activity activity) {
}
@Override
public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {
}
@Override
public void onActivityDestroyed(@NonNull Activity activity) {
}
};
当监听到 Activity 的 onDestroy 方法后,会将其传给 RefWatcher 的 watch 方法
在其watch()方法中,主要操作
ensureGoneAsync 方法操作,其中实现了内存泄漏的检测
遍历 ReferenceQueue 中所有的元素,并根据每个元素中的 key,相应的将集合 retainedKeys 中的元素也删除
判断集合 retainedKeys 是否还包含被检测对象的弱引用,包含说明被检测对象并没有被回收,发生了内存泄漏
生成 Heap “堆”信息,并生成内存泄漏的分析报告
向主线程 MessageQueue 中插入了一个 IdleHandler,IdleHandler 只会在主线程空闲时才会被 Looper 从队列中取出并执行。通过 addIdleHandler 也经常用来做 App 的启动优化,比如在 Application 的 onCreate 方法中经常做 3 方库的初始化工作。可以将优先级较低、暂时使用不到的 3 方库的初始化操作放到 IdleHandler 中,从而加快 Application 的启动过程
//getMainLooper().myQueue()或者Looper.myQueue()
Looper.myQueue().addIdleHandler(new IdleHandler() {
@Override
public boolean queueIdle() {
//你要处理的事情
return false;
}
});
本文地址:https://blog.csdn.net/ZKhero/article/details/107150905
如对本文有疑问, 点击进行留言回复!!
LongClick原理、上下文菜单原理、EditText长按弹窗原理、WebView长按弹窗自定义、修复WebView全选重复bug ———————————————— 版权声明:本文为CSDN博主「
JobScheduler 实现 特定时间,特定条件(系统空闲,电池电量,磁盘空间 ……)下执行任务
温习Android基础知识——《第一行代码(第三版)》读书笔记 Chapter 10 Service
网友评论