BottomSheetDialogFragment、DialogFragment内存泄漏记录

项目开发中大多会使用leakcanary内存泄漏检测工具检测内存泄漏,leakcanary检测会发现BottomSheetDialogFragment、DialogFragment有内存泄漏情况。如果还不清楚为什么出现内存泄漏,请移步Google或百度;这里不详细描述为什么内存泄露了,默认你已经知道了为什么BottomSheetDialogFragment、DialogFragment有内存泄漏情况。(如有问题欢迎指正!)

解决步骤:(已真机测试)

1、新建一个DialogInterfaceProxy类,用来持有Dialog中DialogInterface接口下的OnCancelListener、OnDismissListener、OnShowListener真正的回调,代码如下:

public class DialogInterfaceProxy {
    public static DialogInterface.OnCancelListener proxy(DialogInterface.OnCancelListener onCancelListener) {
        return new ProxyOnCancelListener(onCancelListener);
    }

    public static DialogInterface.OnDismissListener proxy(DialogInterface.OnDismissListener onDismissListener) {
        return new ProxyOnDismissListener(onDismissListener);
    }

    public static DialogInterface.OnShowListener proxy(DialogInterface.OnShowListener onShowListener) {
        return new ProxyOnShowListener(onShowListener);
    }

    /**
     * 使用弱引用持有Dialog真正的DialogInterface.OnCancelListener,
     * 

* 即使Message.obj未被正常释放,最终它持有的也只是ProxyOnCancelListener的一个空壳实例 */ public static class ProxyOnCancelListener implements DialogInterface.OnCancelListener { private WeakReference<DialogInterface.OnCancelListener> mProxyRef; public ProxyOnCancelListener(DialogInterface.OnCancelListener onCancelListener) { mProxyRef = new WeakReference<>(onCancelListener); } @Override public void onCancel(DialogInterface dialog) { DialogInterface.OnCancelListener onCancelListener = mProxyRef.get(); if (onCancelListener != null) { onCancelListener.onCancel(dialog); } } } /** * 使用弱引用持有Dialog真正的DialogInterface.OnDismissListener, *

* 即使Message.obj未被正常释放,最终它持有的也只是ProxyOnDismissListener的一个空壳实例 */ public static class ProxyOnDismissListener implements DialogInterface.OnDismissListener { private WeakReference<DialogInterface.OnDismissListener> mProxyRef; public ProxyOnDismissListener(DialogInterface.OnDismissListener onDismissListener) { mProxyRef = new WeakReference<>(onDismissListener); } @Override public void onDismiss(DialogInterface dialog) { DialogInterface.OnDismissListener onDismissListener = mProxyRef.get(); if (onDismissListener != null) { onDismissListener.onDismiss(dialog); } } } /** * 使用弱引用持有Dialog真正的DialogInterface.OnShowListener, *

* 即使Message.obj未被正常释放,最终它持有的也只是ProxyOnShowListener的一个空壳实例 */ public static class ProxyOnShowListener implements DialogInterface.OnShowListener { private WeakReference<DialogInterface.OnShowListener> mProxyRef; public ProxyOnShowListener(DialogInterface.OnShowListener onShowListener) { mProxyRef = new WeakReference<>(onShowListener); } @Override public void onShow(DialogInterface dialog) { DialogInterface.OnShowListener onShowListener = mProxyRef.get(); if (onShowListener != null) { onShowListener.onShow(dialog); } } } }

2、新建ProxyBottomSheetDialog继承BottomSheetDialog,将其中super.setOnCancelListener、super.setOnDismissListener、super.setOnShowListener参数使用DialogInterfaceProxy类包裹起来,代码如下:

public class ProxyBottomSheetDialog extends BottomSheetDialog {

    public ProxyBottomSheetDialog(@NonNull Context context) {
        super(context);
    }

    public ProxyBottomSheetDialog(@NonNull Context context, int theme) {
        super(context, theme);
    }

    protected ProxyBottomSheetDialog(@NonNull Context context, boolean cancelable, OnCancelListener cancelListener) {
        super(context, cancelable, cancelListener);
    }

    @Override
    public void setOnCancelListener(@Nullable OnCancelListener listener) {
        super.setOnCancelListener(DialogInterfaceProxy.proxy(listener));
    }

    @Override
    public void setOnDismissListener(@Nullable OnDismissListener listener) {
        super.setOnDismissListener(DialogInterfaceProxy.proxy(listener));
    }

    @Override
    public void setOnShowListener(@Nullable OnShowListener listener) {
        super.setOnShowListener(DialogInterfaceProxy.proxy(listener));
    }
}

3、新建ProxyBottomSheetDialogFragment继承BottomSheetDialogFragment,重写onCreateDialog方法,该方法中改为自定义的ProxyBottomSheetDialog,代码如下:

public class ProxyBottomSheetDialogFragment extends BottomSheetDialogFragment {

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        if (getContext() == null) {
            return super.onCreateDialog(savedInstanceState);
        }
        return new ProxyBottomSheetDialog(getContext(), getTheme());
    }
}

4、DialogFragment处理同上2、3步骤!!!

你可能感兴趣的:(Android)