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

内存泄漏原因

所有语言的内存泄漏无非就是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);
/// /// pri
Flutter 应用程序在运行过程中可能会遇到内存泄漏的问题,这会显著影响应用性能甚至导致崩溃。以下是关于如何排查 Flutter内存泄漏的一些常见步骤及建议: ### 一、了解常见的内存泄漏原因 1. **未释放的Stream订阅** 如果你在应用程序中使用了 `Stream` 或者其他异步数据流,在不需要的时候未能取消订阅,就可能导致内存无法回收。 2. **Widget树中的状态持有对象** 当 Widget 被销毁但仍有一些引用指向它内部的状态或其他资源时,该部分可能不会被垃圾收集机制清理掉。 3. **全局变量或单例模式滥用** 使用不当的全局变量或者单例设计也可能造成不必要的长期持有对象实例的情况。 4. **Timer 和 AnimationController 没有正确关闭** 这些定时任务如果没有及时清除,将一直占用系统资源直到超时结束。 5. **图片加载库缓存策略设置错误** 图片处理相关的第三方插件如果配置不合理也容易引发此类问题。 --- ### 二、工具支持与检测手段 #### (一)Dart DevTools Flutter 提供了一个强大的调试工具——DevTools,可以用来监控内存使用情况并查找潜在泄露点。 - 打开项目后通过命令行输入 `flutter pub global activate devtools` 安装; - 然后可以在 VSCode 或 Android Studio 的 Dart Analysis 面板启动分析视图查看详细的Heap信息; #### (二)Memory Profiling in Flutter Performance Mode (Performance Overlay) 启用性能覆盖层可以帮助开发者直观地观察帧率变化以及堆栈分配趋势等重要指标是否异常激增。 #### (三)LeakCanary for Android平台专属方案 对于跨端开发而言,单独针对安卓设备还可以集成 LeakCanary 来精确捕捉Java/Kotlin层面的泄密现象,并生成报告指导修复工作流程。 --- ### 三、实际操作指南 1. **检查 Stream 订阅** ```dart @override void dispose() { _streamSubscription?.cancel(); super.dispose(); } ``` 2. **管理 Timer 生命周期** ```dart late final Timer timer; // 初始化计时器... if (timer.isActive) { timer.cancel(); } else { /* do nothing */ } ``` 3. **清理 ImageCache 缓存** 可以主动清空图像缓冲区来避免大量静态展示区域消耗过多存储空间: ```dart PaintingBinding.instance!.imageCache.clear(); ``` 4. **移除多余的监听事件** 对于某些需要频繁更新UI控件的操作应特别注意解除绑定关系如TextEditingController等组件。 --- 总之,在日常编码实践中养成良好习惯至关重要,例如遵循RAII原则(Resource Acquisition Is Initialization),即“构造函数获取资源,析构函数释放资源”。此外定期运用专业软件辅助审查源码质量亦不可或缺!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值