【问题标题】:Why do we use the dispose() method in Flutter Dart code?为什么我们在 Flutter Dart 代码中使用 dispose() 方法?
【发布时间】:2020-01-02 05:21:35
【问题描述】:

为什么我们使用dispose() 方法?我对此有点困惑。 如果我们不使用它会出现什么问题,使用它有什么好处?

@override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
  }

【问题讨论】:

  • 'dispose()' 在 State 对象被移除时调用,是永久的
  • dispose 方法不适用于 Dart 语言。仅适用于 Flutter 平台。

标签: flutter dart


【解决方案1】:

dispose方法用于在状态对象被移除时释放分配给变量的内存。

例如,如果您在应用程序中使用流,那么您必须释放分配给流控制器的内存。否则,您的应用可能会从 PlayStore 和 AppStore 收到有关内存泄漏的警告。

【讨论】:

  • 先生,请您解释一下内存泄漏的问题吗?
  • 内存泄漏是一种资源泄漏,当计算机程序错误地管理内存分配时,不再需要的内存不会被释放。
  • 那么先生,如果发生内存泄漏会产生什么问题?有什么例子吗?
  • 内存泄漏可能导致内存不足错误,在最好的情况下 1) 您的应用程序将被操作系统意外终止并且用户体验不佳。在最坏的情况下,2)它还可能导致整个系统性能不佳,因为您的应用程序正在慢慢“吃掉”所有可用内存,而操作系统必须处理如此大量的虚拟内存,不得不不断页面以使您的程序快乐,同时保持一切正常运行。长话短说 -> 你的整个系统变得草率且反应迟钝。
  • 恕我直言,这个答案令人困惑。 Dart 是一种垃圾收集语言,这通常意味着不需要手动释放内存。与手动内存管理相比,您不必例如释放dispose中字符串的内存。我假设只有当某些东西阻止引用计数达到零时才需要一个不平凡的dispose,这是感知内存泄漏的真正原因。我仍然不清楚在什么情况下会发生这种情况。
【解决方案2】:

dispose() 方法如果未定义则自动从有状态调用。

在某些情况下需要 dispose,例如 CameraPreviewTimer 等。您必须关闭流。

当需要关闭流时,您必须在 dispose 方法中使用它。

dispose() 用于在屏幕被释放时执行代码。相当于Android的onDestroy()

例子:

@override
void dispose() {
  cameraController?.dispose();
  timer.cancel();
  super.dispose();
}

【讨论】:

  • 好吧,现在我开始理解 dispose() ==onDestroy() 的意思了。如果我不使用它呢?
  • 如果您没有使用任何需要强制关闭流的特殊功能,例如 Timer、CameraPreview 等,则不需要强制覆盖和使用它。
  • 这就是我需要的。执行!谢谢!
  • dispose还有什么实现? @ParthPatel
  • 哪些情况需要人工处理?你只提到了两种情况。想知道这个。 @ParthPatel
【解决方案3】:

主要目的是获得一个回调,您可以在其中释放所有资源。

如果您已初始化某个状态中的任何资源,请务必在释放该状态时关闭或销毁该资源。

例如:如果您在 StatefullWidget 的 initState 中创建一个流,那么请务必在该状态的 dispose 方法中关闭该流,否则会导致内存泄漏。

更多细节可以参考我从StatefulWidgetdispose方法的源代码中得到的以下cmets:

从树中永久删除此对象时调用。这 当此 [State] 对象永远不会构建时,框架会调用此方法 再次。框架调用[dispose]后,[State]对象为 被认为已卸载并且 [mounted] 属性为 false。它是一个 此时调用 [setState] 时出错。生命周期的这个阶段是 终端:没有办法重新挂载一个已经挂载的 [State] 对象 处置。子类应重写此方法以释放任何 此对象保留的资源(例如,停止任何活动动画)。 {@macro flutter.widgets.subscriptions} 如果您覆盖它,请确保 通过调用 super.dispose() 来结束您的方法。也可以看看: * [deactivate],在[dispose]之前调用。

或者您可以参考文档:https://api.flutter.dev/flutter/widgets/State/dispose.html

因此,当当前状态将不再被使用时,基本上会调用 dispose。因此,如果您有任何侦听器在该状态下处于活动状态,那么它们可能会导致内存泄漏,因此您应该关闭它们。

【讨论】:

    【解决方案4】:

    从树中永久删除此对象时调用dispose()方法。

    更多信息可以参考官方文档:https://api.flutter.dev/flutter/widgets/State/dispose.html

    实现示例:

    @protected
    @mustCallSuper
    void dispose() {
      assert(_debugLifecycleState == _StateLifecycle.ready);
      assert(() {
        _debugLifecycleState = _StateLifecycle.defunct;
        return true;
      }());
    }
    
    

    【讨论】:

      【解决方案5】:

      一般来说dispose 意味着在相关对象从焦点中移除之前释放资源。重点是指来自widget treenavigation stack,无论哪个相关。

      当您对 widget state 调用 dispose 时,关联的小部件应该是 unmounted,这意味着该小部件永远不会重建。

      从树中永久删除此对象时调用。

      当此 State 对象永远不会再次构建时,框架会调用此方法。

      框架调用dispose后,认为State对象未挂载,挂载 属性为假。此时调用 setState 是错误的。

      生命周期的这个阶段是终端:没有办法重新挂载一个已经被 处置。

      当您在 bloc 上调用 dispose 时,该集团应该关闭 eventstate 流。 更新:新集团没有dispose,而是有close

      所以,这就是dispose 的基本含义。

      TL;DR 一般来说,这意味着释放关联的实例/对象所持有的资源。

      不过,dispose 的具体含义会随着调用该方法的对象的类型而变化。

      【讨论】:

        【解决方案6】:

        您不仅应该重写 dispose 方法以释放一些内存,还应该像 BannerAd 一样处置那些原本在屏幕上可见的对象。

        假设您有一个BannerAd,但您没有释放bannerAd 的实例并导航回上一页,您的广告仍会出现在您不希望的屏幕上。所以,你必须像这样处理它:

        @override
        void dispose() {
          bannerAd?.dispose();
          super.dispose();
        }
        

        【讨论】:

          【解决方案7】:

          我们使用dispose() 方法来在从小部件树中删除状态对象时停止/避免内存链接。

          【讨论】:

            【解决方案8】:

            鉴于以上关于垃圾收集的所有答案以及在 dispose() 中放入什么的示例,似乎一般的想法是处置/取消任何具有未来或与硬件访问相关的东西,因为你不想要返回一个不存在的对象或阻止其他应用使用该资源(例如相机、文件系统、麦克风等)。

            【讨论】:

              猜你喜欢
              • 2022-08-23
              • 2021-10-01
              • 2020-12-24
              • 2019-03-16
              • 1970-01-01
              • 2021-06-03
              • 2011-08-13
              • 1970-01-01
              • 2020-07-16
              相关资源
              最近更新 更多