Android开发dialog内存泄露,DialogFragmen引起的内存泄露

  • Post author:
  • Post category:其他


一、简介

DialogFragment是Android3.0之后引入的一种特殊的Fragment,官方建议使用DialogFragment代替Dialog或者AllertDialog来实现弹框的功能,因为它可以更好的管理Dialog的生命周期以及可以更好复用。

二、使用中遇到内存泄露

在使用过程中,由于业务需要对DialogFragment的dismiss事件进行了监听,在DialogFragment展示与消失的时候,经常会出现LeakCanary检测的内存泄露问题。查看LeakCanary的内存泄露引用链如下图所示:

ad1d77207ea2

image.png

这里只贴出了一张图,LeakCanary每次报出来的引用链并不完全相同,图上中显示的是RxJava的ThreadHandler,有的则显示的是高德地图的ThreadHandler(amapLocManagerThread),由此猜测这里并不是主线程的ThreadHandler引起的内存泄露,而是第三方库中的ThreadHandler引起的内存泄露。但总的来说都是HandlerThread中处理的Message引用了NormalTitleBgDialog(DialogFragment)不能被释放。下面具体分析一下出现这个问题的原因。

三、原因分析

那么Message是怎么引用到DialogFragment的呢?在DialogFragment中搜索一下Message一无所获。DialogFragment实际是Dialog的封装,在Dialog中搜索Message试试,果然发现Dialog的Cancle和Dismiss都是通过Handler进行操作的,从这里入手分析一下内存泄露的原因:

DialogFragment中的onActivityCreated

Cancle和Dismiss的监听传入的是DialogFragment实现的两个接口:DialogInterface.OnCancelListener, DialogInterface.OnDismissListener

@Override

public void onActivityCreated(@Nullable Bundle savedInstanceState) {

super.onActivityCreated(savedInstanceState);

mDialog.setOnCancelListener(this);

mDialog.setOnDismissListener(this);

}

setOnDismissListener

这里会通过mListenerHandler获取到一个mDismissMessage对象。

public void setOnDismissListener(@Nullable OnDismissListener listener) {

if (listener != null) {

mDismissMessage = mListenersHandler.obtainMessage(DISMISS, listener);

} else {

mDismissMessage = null;

}

}

public void setOnCancelListener(@Nullable OnCancelListener listener) {

if (listener != null) {

mC