DialogFragment内存泄露问题能不能一次性改好

文章讲述了在Android开发中,作者遇到NoLeakDialog在某些情况下重复弹出的问题,原因在于DialogFragment的dismiss机制。通过分析,作者发现需要在NoLeakDialog中重写dismiss方法以确保正确回调并调用Fragment的dismiss方法,以避免意外重现。
摘要由CSDN通过智能技术生成

public NoLeakDialog(@NonNull Context context, int themeResId) {

super(context, themeResId);

}

@Override

public void setOnCancelListener(@Nullable OnCancelListener listener) {

// 空实现,不持有外部的引用

}

@Override

public void setOnShowListener(@Nullable OnShowListener listener) {

// 空实现,不持有外部的引用

}

@Override

public void setOnDismissListener(@Nullable OnDismissListener listener) {

// 空实现,不持有外部的引用

}

@Override

public void setCancelMessage(@Nullable Message msg) {

// 空实现,不持有外部的引用

}

@Override

public void setDismissMessage(@Nullable Message msg) {

// 空实现,不持有外部的引用

}

}

然后在我们的继承的DialogFramment的onCreateDialog方法中返回我们的NoLeakDialog即可。

至此我自己内心不得不为我这个高级划水师惊人的隐藏bug能力叹服,赶紧泡一杯枸杞喝起来准备下一轮的划水。

几杯枸杞水下肚,正准备倒计时下班时,测试带着奸笑跑过来说你这个弹窗不对啊,我点击了空白处隐藏了弹窗,跳转到别的页面后再返回,这个弹窗又自己弹出来了。。。

此时我怀着高级划水师应有的自信直接怼回去说肯定是你的操作方式有问题,一边私底下偷偷打开AS调试起来。。。。

一顿操作猛如虎之后我们发现按返回键和点击空白区域返回键只是调用了Dialog的dismiss放,并没有调用DialogFragment的dismiss方法,因为点击空白区域或者返回键需要Dialog

回调DialogFragment才会调用DialogFragment的dismiss方法,但是我们在NoLeakDialog类中将这些监听器都变成了空实现,所以也就没有了回调。

而在DialogFragment的onDismiss方法方法中我们看到了官方的注释:

@Override

public void onDismiss(@NonNull DialogInterface dialog) {

if (!mViewDestroyed) {

// Note: we need to use allowStateLoss, because the dialog

// dispatches this asynchronously so we can receive the call

// after the activity is paused. Worst case, when the user comes

// back to the activity they see the dialog again.

dismissInternal(true, true);

}

}

注释已经很清楚地说明了DialogFragmen会再次弹出

对于这个问题,我们只要在我们NoLeakDialog中重写dismiss方法,将相关事件回调给DialogFragment,然后调用DialogFragment的dismiss或者dismissAllowingStateLoss方法即可。

所以我们最终NoLeakDialog的代码应该这样:

public class NoLeakDialog extends Dialog {

private WeakReference hostFragmentReference;

public void setHostFragmentReference(DialogFragment hostFragment) {

this.hostFragmentReference = new WeakReference<>(hostFragment);

}

public NoLeakDialog(@NonNull Context context, int themeResId) {

super(context, themeResId);

}

@Override

public void setOnCancelListener(@Nullable OnCancelListener listener) {

// 空实现,不持有外部的引用

}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
img

总结

其实要轻松掌握很简单,要点就两个:

  1. 找到一套好的视频资料,紧跟大牛梳理好的知识框架进行学习。
  2. 多练。 (视频优势是互动感强,容易集中注意力)

你不需要是天才,也不需要具备强悍的天赋,只要做到这两点,短期内成功的概率是非常高的。

对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。

以上就是总结的关于在面试的一些总结,希望对大家能有些帮助,除了这些面试中需要注意的问题,当然最重要的就是刷题了,这里放上我之前整理的一份超全的面试专题PDF,大家有兴趣的可以自行领取或者私信我:

还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

【Android核心高级技术PDF文档,BAT大厂面试真题解析】点击:Android架构视频+BAT面试专题PDF+学习笔记即可获取!查看免费领取方式!

省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

【Android核心高级技术PDF文档,BAT大厂面试真题解析】点击:Android架构视频+BAT面试专题PDF+学习笔记即可获取!查看免费领取方式!

[外链图片转存中…(img-enqjYnPN-1710657275125)]

这里只是整理出来的部分面试题,后续会持续更新,希望通过这些高级面试题能够降低面试Android岗位的门槛,让更多的Android工程师理解Android系统,掌握Android系统。喜欢的话麻烦点击一个喜欢在关注一下~

DialogFragment的内存泄漏通常是由于它与Activity的生命周期不一致而导致的。比如,在DialogFragment中使用了Activity的Context,而DialogFragment在Activity销毁之前没有被销毁,那么Activity所持有的DialogFragment引用就会一直存在,从而导致内存泄漏。 解决方法有以下几种: 1. 尽量避免在DialogFragment中持有Activity的引用,使用Application Context或者其他非Activity的Context。 2. 在DialogFragment中使用静态内部类或者弱引用来持有Activity的引用,从而避免内存泄漏。 3. 在DialogFragment的onDetach()方法中将Activity的引用置为null,从而解除对Activity的引用,让GC可以回收DialogFragment。 以下是一个使用静态内部类来避免DialogFragment内存泄漏的例子: ``` public class MyDialogFragment extends DialogFragment { private static WeakReference<Activity> sActivityRef; public static void show(Activity activity) { sActivityRef = new WeakReference<>(activity); MyDialogFragment dialogFragment = new MyDialogFragment(); dialogFragment.show(activity.getFragmentManager(), "MyDialogFragment"); } @Override public void onAttach(Context context) { super.onAttach(context); if (sActivityRef != null) { Activity activity = sActivityRef.get(); if (activity != null) { // do something with activity } } } @Override public void onDetach() { super.onDetach(); sActivityRef = null; } } ``` 使用时,可以调用MyDialogFragment.show()方法来显示DialogFragment,这样就可以避免在DialogFragment中持有Activity的引用,避免内存泄漏。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值