2分钟教你Flutter怎么避免引用内存泄漏

2分钟教你Flutter怎么避免引用内存泄漏

  • 内存泄漏原因
    • 1. 在当前类,或者方法等移除改引用,让其他自动释放,等下一轮GC扫描释放。如
    • 2. 使用弱引用-----**WeakReference**,当前使用完,生命周期结束后,自动释放。
    • 使用vm_service插件触发GC

内存泄漏原因

所有语言的内存泄漏无非就是GC Root(线程,全局或静态数组或引用等)的引用链持有了需要释放的引用,导致无法释放。
解决释放的方法,无非就是2种,如下:
在这里插入图片描述

1. 在当前类,或者方法等移除改引用,让其他自动释放,等下一轮GC扫描释放。如

class B{void doSomething(){}
}class A{B? b;
}
A a = A();
void test(){a.b = B();a.b?.doSomething();
}void dispose(){a.b = null;
}void main() {test();dispose();
}

A 这时候时全局的,如果使用完B后,想要B自动释放,只需要调用dispose() 将B置null就好。

然后,现实就是有可能,忘记调用dispose().导致B无法释放。怎么办呢?对,你猜到了,就是弱引用,Dart也有!

来了来了就是那个闪亮的仔, WeakReference(和Java的弱引用名字一样哦)

2. 使用弱引用-----WeakReference,当前使用完,生命周期结束后,自动释放。

在上面代码,B的生命周期,仅仅是在test这个方法里面,所以执行test后B就不需要用了,那么就让他自动等GC移除.
让我们看看他的源码

/// A weak reference to a Dart object.
///
/// A _weak_ reference to the [target] object which may be cleared
/// (set to reference `null` instead) at any time
/// when there is no other way for the program to access the target object.
///
/// _Being the target of a weak reference does not keep an object
/// from being garbage collected._
///
/// There are no guarantees that a weak reference will ever be cleared
/// even if all references to its target are weak references.
///
/// Not all objects are supported as targets for weak references.
/// The [WeakReference] constructor will reject any object that is not
/// supported as an [Expando] key.
///
/// Use-cases like caching can benefit from using weak references. Example:
///
/// ```dart
/// /// [CachedComputation] caches the computation result, weakly holding
/// /// on to the cache.
/// ///
/// /// If nothing else in the program is holding on the result, and the
/// /// garbage collector runs, the cache is purged, freeing the memory.
/// ///
/// /// Until the cache is purged, the computation will not run again on
/// /// a subsequent request.
/// ///
/// /// Example use:
/// /// ```
/// /// final cached = CachedComputation(
/// ///     () => jsonDecode(someJsonSource) as Object);
/// /// print(cached.result); // Executes computation.
/// /// print(cached.result); // Most likely uses cache.
/// /// ```
/// class CachedComputation<R extends Object> {
///   final R Function() computation;
///
///   WeakReference<R>? _cache;
///
///   CachedComputation(this.computation);
///
///   R get result {
///     final cachedResult = _cache?.target;
///     if (cachedResult != null) {
///       return cachedResult;
///     }
///
///     final result = computation();
///
///     // WeakReferences do not support nulls, bools, numbers, and strings.
///     if (result is! bool && result is! num && result is! String) {
///       _cache = WeakReference(result);
///     }
///
///     return result;
///   }
/// }
/// ```
("2.17")
abstract class WeakReference<T extends Object> {/// Creates a [WeakReference] pointing to the given [target].////// The [target] must be an object supported as an [Expando] key,/// which means [target] cannot be a number, a string, a boolean, a record,/// the `null` value, or certain other types of  special objects.external factory WeakReference(T target);/// The current object weakly referenced by [this], if any.////// The value is either the object supplied in the constructor,/// or `null` if the weak reference has been cleared.T? get target;
}

好家伙,上面就用例子叫我们怎么使用,属性target就是获取当前需要的引用。让我们改改上面


class B{void doSomething(){}
}class A{WeakReference<B>? b;
}
A a = A();
void test(){a.b = WeakReference(B());a.b?.target?.doSomething();
}void dispose(){a.b = null;
}void main() {test();print(a.b?.target);
}

让我们执行下,看看结果
控制台:

Instance of ‘B’

??? ,有同学就问,怎么还持有,怎么还不释放。
因为当前没触发GC垃圾回收器,所以没必要进行回收。看过我这篇文章Android内存抖动
的同学知道,因为频繁回收会出现内存抖动现象,从而导致App掉帧甚至卡顿现象,GC垃圾回收器在这做了优化。那如果真的想测试验证这个结果,怎么办?
可以2种方案,第一种,老套路啦,强制制造大量无效垃圾引用,让GC触发回收。
如:制造大量的引用,并且需要释放的引用

void main() {test();List.generate(10000, (index) {ByteData byteData = ByteData(10000);});print(a.b?.target);
}

让我们执行下,看看结果
控制台:

null

当当当~,回收了吧

使用vm_service插件触发GC

还有一种办法,就是调用vm_service插件提供的VmService进行回收。注意一点是,这个GC做了优化,回收是单独对线程进行回收的,所以需要筛选对应的线程进行回收,如我们的线程基本是在UI线程也就是main线程中进行的,那么我们就筛选main


class VmServiceHelper {bool debug = false;VmServiceHelper() {assert(() {debug = true;return true;}());}VmService? _vmService;VM? _vm;Uri? _observatoryUri;Future<VmService?> getVmService() async {if (_vmService == null && debug) {ServiceProtocolInfo serviceProtocolInfo = await Service.getInfo();_observatoryUri = serviceProtocolInfo.serverUri;if (_observatoryUri != null) {Uri url = convertToWebSocketUrl(serviceProtocolUrl: _observatoryUri!);try {_vmService = await vmServiceConnectUri(url.toString());} catch (error, stack) {print(stack);}}}return _vmService;}Future try2GC() async {if (!debug) {return;}final vms = await getVmService();if (vms == null) return null;final isolate = await getMainIsolate();if (isolate?.id != null) {await vms.getAllocationProfile(isolate!.id!, gc: true);}}Future<Isolate?> getMainIsolate() async {if (!debug) {return null;}IsolateRef? ref;final vm = await getVM();if (vm == null) return null;var index = vm.isolates?.indexWhere((element) => element.name == 'main');if (index != -1) {ref = vm.isolates![index!];}final vms = await getVmService();if (ref?.id != null) {return vms?.getIsolate(ref!.id!);}return null;}Future<VM?> getVM() async {if (!debug) {return null;}return _vm ??= await (await getVmService())?.getVM();}
}

在使用之前,我们需要在运行配置上面加入

VsCode

{..."args": ["--disable-dds"],"type": "dart"},

Android Studio
在这里插入图片描述

然后我们使用VmServiceHelper().try2GC(),代替上面的语句如下。但是需要运行app来测试。

test();
await VmServiceHelper().try2GC();
print(a.b?.target);

好了,如果本次文章觉得对你有用,请点赞,收藏,关注3连谢谢。
需要VmServiceHelper这个的朋友,可以到 flutter_leak_canary: ^1.0.1这个上面下载哦,如果顺手,给我点个Like哟

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/7039.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VTK —— 三、图形格式 - 示例1 - 读取.vtp文件并输出.ply文件(附完整源码)

代码效果&#xff1a;演示程序读取.vtp后输出.ply文件&#xff0c;使用paraview打开该输出的.ply文件 本代码编译运行均在如下链接文章生成的库执行成功&#xff0c;若无VTK库则请先参考如下链接编译vtk源码&#xff1a; VTK —— 一、Windows10下编译VTK源码&#xff0c;并用V…

opencv图像处理详细讲

传统的计算机视觉框架&#xff1a; SimpleCV BoofCV Dlib JavaCV 深度学习计算机视觉框架 Caffe Tensorflow Pytorch Paddlepaddle Keras 深度视觉计算机视觉框架 OpenVINO TensorRT onnxruntime Deepface YOLO/DarkNet mmdetection Paddle-detection/seg/ocr …

重识来伊份:抢滩首店经济,休闲零食品牌的“面子”和“里子”

前不久&#xff0c;苹果静安零售店的首秀频频登上热搜。 这背后&#xff0c;不仅仅因为它是中国大陆最大的苹果旗舰店&#xff0c;还在于它的设计融入了时尚又古典的上海街区&#xff0c;吸引了众多市民拍照打卡。今年3月至5月&#xff0c;上海会持续举办“首发上海”春季系列…

电能计量抄表系统

1.电能计量抄表系统的概念和作用 电能计量抄表系统是一种前沿的自动化控制&#xff0c;主要运用于电力行业的电费计算及管理。它通过远程数据采集和处理&#xff0c;实时监控系统用户的用电状况&#xff0c;取代了传统的手工抄水表方法&#xff0c;降低了成本&#xff0c;降低…

五、VGA 叠加图像原理和实现(十字光标)

前言&#xff1a;该案例在VGA项目&#xff1a;联合精简帧双fifosobel算法 实现VGA显示项目的基础上进行改动。 要求&#xff1a;通过串口助手把 198x198 的十字光标图像二进制数据传递给 FPGA 板卡&#xff0c;FPGA 板 卡接收到后存储到 Ram 中用于 VGA 叠加显示。 预期效果展…

020、Python+fastapi,第一个Python项目走向第20步:ubuntu 24.04 docker 安装mysql8集群+redis集群(一)

系列文章 pythonvue3fastapiai 学习_浪淘沙jkp的博客-CSDN博客https://blog.csdn.net/jiangkp/category_12623996.html 前言 docker安装起来比较方便&#xff0c;不影响系统整体&#xff0c;和前面虚拟环境有异曲同工之妙&#xff0c;今天把老笔记本T400拿出来装了个ubuntu24…

小程序激励广告视频多次回调问题

1.问题 2. 激励视频使用及解决方案 官方文档 let videoAd null; // 在页面中定义激励视频广告 Page({/*** 页面的初始数据*/data: {},/*** 生命周期函数--监听页面加载*/onLoad(options) {let that this;// 创建激励视频广告实例if (wx.createRewardedVideoAd) {videoAd w…

知识库工具:付费的HelpLook AI知识库比免费的牵牛易帮好在哪里

在知识管理的领域中&#xff0c;选择合适的知识库工具对于企业来说很重要。市面上有很多知识库产品&#xff0c;有付费的和免费的&#xff0c;但是还是有很多企业会选择使用付费的&#xff0c;而不是免费的。这是为什么呢&#xff1f;这就是今天要探讨的问题&#xff0c;下面就…

Android虚拟机机制

目录 一、Android 虚拟机 dalvik/art&#xff08;6版本后&#xff09;二、Android dex、odex、oat、vdex、art区别 一、Android 虚拟机 dalvik/art&#xff08;6版本后&#xff09; 每个应用都在其自己的进程中运行&#xff0c;都有自己的虚拟机实例。ART通过执行DEX文件可在设…

什么是B2B SaaS公司?

前言 在当今数字化时代&#xff0c;B2B SaaS公司正在以惊人的速度崛起&#xff0c;成为企业界的一股重要力量。但是&#xff0c;对于许多人来说&#xff0c;B2B SaaS究竟是什么&#xff0c;以及它如何影响商业生态&#xff0c;可能还是一片未知。本文将简要介绍B2B SaaS公司的…

Python+Selenium 实现自动化测试

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号【互联网杂货铺】&#xff0c;回复 1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 安装selenium 打开命令控制符输入&#xff1a;pip install -U …

网络安全----小程序渗透测试反编译审计漏洞

一、什么是反编译审计漏洞 微信小程序反编译渗透测试是一种针对微信小程序的安全测试方法&#xff0c;是在通过对小程序源代码的反编译和分析&#xff0c;发现潜在的安全漏洞&#xff0c;并对其进行渗透测试以验证其安全性的一种方法。 二、测试流程及其步骤 反编译小程序&a…

C#知识|如何在WinForm窗体中实现分割线绘制?

哈喽&#xff0c;你好啊&#xff0c;我是雷工&#xff01; 在上位机UI设计中经常会用到分割线&#xff0c;用来分割界面区域。 像在KingSCADA、杰控、昆仑通态、WinCC、组态王、力控、易控等组态软件中非常简单&#xff0c;有现成的划线操作&#xff0c;选中相关工具直接绘制即…

颠覆传统?「一束光子,两种频率」的量子纠缠!

在最新的研究中&#xff0c;科学家们开发了一种革命性的量子纠缠方式——“频域光子数路纠缠”&#xff08;frequency-domain photon number-path entanglement&#xff09;。这一量子物理学的重大进展涉及到一个创新性的工具&#xff1a;频率分束器&#xff08;frequency beam…

jmeter后置处理器提取到的参数因为换行符导致json解析错误

现象&#xff1a; {"message":"JSON parse error: Illegal unquoted character ((CTRL-CHAR, code 10)): has to be escaped using backslash to be included in string value; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Ill…

开源之夏 2024 学生报名通道现已正式开启!奖金都是12000元,冲啊!!!

Apache SeaTunnel作为数据集成平台的先行者&#xff0c;数以千计的开发者活跃在这个开源社区&#xff0c;我们深知开源社区就像是“众人拾柴火焰高”&#xff0c;希望有更多的青年力量能参与到社区的建设中来&#xff01; 在前段时间&#xff0c;我们不仅成功入选中科院软件所主…

[C++]VS2022配置cplex12.8过程中出现ext未声明标识符语法错误:标识符“ImplClass“

这个时候&#xff0c;主要的是看报错&#xff0c;根据报错&#xff0c;去网上寻找解决办法。因为这个时候&#xff0c;代码可能并没有任何错误&#xff0c;只不过你是VS2022&#xff0c;老师是VS2017或者其他版本。不同的版本之间代码运行问题&#xff0c;如果你换成cplex12.10…

【前端】输入时字符跳动动画实现

输入时字符跳动动画实现 在前端开发中&#xff0c;为了提升用户体验&#xff0c;我们经常需要为用户的交互行为提供即时的反馈。这不仅让用户知道他们的操作有了响应&#xff0c;还可以让整个界面看起来更加生动、有趣。本文将通过一个简单的例子讲解如何实现在用户输入字符时…

速卖通自养号测评海外环境:成本、步骤、技巧全掌握

相信不少涉足跨境业务的企业和商家都对速卖通耳熟能详。作为当下炙手可热的跨境电商平台&#xff0c;速卖通在国内电商市场渐趋饱和的背景下&#xff0c;吸引了众多国内卖家的目光。他们纷纷入驻速卖通&#xff0c;希望借助这一平台的力量&#xff0c;成功打通跨境业务渠道。然…

重新下载 ant design pronp

一、项目重建 要删除前端代码并 重新下载Ant Design Pro&#xff0c;您可以按照以下步骤操作&#xff1a; 删除项目文件夹&#xff1a;找到您的Ant Design Pro项目文件夹&#xff0c;将其完全删除。清除npm缓存&#xff1a;在命令行中运行npm cache clean --force以清除npm的缓…