【问题标题】:Component unmount in flutter (equivalent of React componentWillUnmount) - Flutter webFlutter中的组件卸载(相当于React componentWillUnmount) - Flutter web
【发布时间】:2021-03-16 20:52:29
【问题描述】:

我有在页面更改时卸载的小部件。

我正在使用颤振网络。

我查看了所有方法 here,但似乎找不到。

我试过了

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

@override
void deactivate() {
  print("deactivate");
  super.deactivate();
}

两者都没有被调用。

当小部件没有“构建”(渲染)时,我需要检测这是一件非常简单的事情。我不认为有一些东西可以检测页面更改是解决方案,这似乎有点矫枉过正。 谢谢

添加代码示例

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(
    title: 'Named Routes Demo',
    initialRoute: '/',
    routes: {
      '/': (context) => FirstScreen(),
      '/second': (context) => SecondScreen(),
    },
  ));
}

class FirstScreen extends StatefulWidget {
  FirstScreen({Key key}) : super(key: key);

  @override
  _FirstScreenState createState() => _FirstScreenState();
}

class _FirstScreenState extends State<FirstScreen> {
  @override
void dispose() {
  print("dispose"); 
  super.dispose();   
}

@override
void deactivate() {
  print("deactivate");
  super.deactivate();
}
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('First Screen'),
      ),
      body: Center(
        child: ElevatedButton(
          child: Text('Launch screen'),
          onPressed: () {
            Navigator.pushNamed(context, '/second');
          },
        ),
      ),
    );
  }
}

class SecondScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Second Screen"),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            // Navigate back to the first screen by popping the current route
            // off the stack.
            Navigator.pop(context);
          },
          child: Text('Go back!'),
        ),
      ),
    );
  }
}

当导航到第二个屏幕并且第一个屏幕小部件不再是渲染树的一部分时,似乎既没有调用 deactive 也没有调用 dispose。那么调用什么来检测 Screen 1 离开了渲染树呢?

【问题讨论】:

  • 所以您是说小部件已卸载,但您没有采取任何措施将其从小部件树中移除?也许发布一些演示该问题的代码会有所帮助。
  • @user1032613 添加。当第一个屏幕停止重新渲染时,我想从第一个屏幕检测。在反应中,我们有带有类的 componentDidUnmount。是否有等效的颤振?

标签: flutter flutter-web


【解决方案1】:

如果 Widget 尚未安装,则返回它。但是你必须在任何 setState 方法之前这样做

if (!mounted) return;
setState(() {});

if (mounted) {
   //your code
};
setState(() {});

您可以在此处阅读更多信息:https://api.flutter.dev/flutter/widgets/State/mounted.html

无论如何,在构建之前唯一调用的是initState。您在其中所做的一切都在build 之前。 初始化状态:https://api.flutter.dev/flutter/widgets/EditableTextState/initState.html

【讨论】:

  • 我看不到在哪里添加这个。我如何知道挂载值是否发生了变化?
  • 您能否提供一个小部件示例,在小部件卸载时仅打印“unmounted”?
【解决方案2】:

在您添加的代码示例中,屏幕 1 永远不会卸载,因此不会触发这些回调。屏幕 2 呈现在屏幕 1 的顶部,并且两者都已安装。

可以确认第1屏一直挂载,通过在其状态中添加周期性回调,添加让它打印出是否还挂载,例如:

  import 'dart:async';
  
  // in _FirstScreenState, add:

  @override
  void initState() {
    Timer.periodic(Duration(seconds: 1), (timer) {
      print("screen 1 is still mounted? $mounted");
    });
    super.initState();
  }

你会看到,它总是挂载的,即使屏幕 2 渲染在屏幕 1 的顶部。

此外,您可以对屏幕 2 执行相同的 deactivatedispose 逻辑,您会看到,当从屏幕 2 导航回屏幕 1 时,屏幕 2 真正卸载,并且两个回调都有效正确。因此再次证明问题不在于这些回调,而是屏幕 1 没有卸载。

所以是的...在您发布代码示例之前,我以为您遇到了一些关于小部件被卸载(已失效)的错误。但是在这种情况下,由于您使用的是按钮,因此可以准确地知道页面转换发生的时间,也许您可​​以在按钮回调中执行您需要执行的任何业务逻辑?

【讨论】:

  • 嗨,谢谢,不,我不能在按钮回调中做到这一点。这是按钮回调正常的示例,但实际情况并非如此。那么,当第 1 页不再可见时,会触发什么功能呢? (无论出于何种原因,无论是卸载还是留在另一个屏幕后面,它都不再是渲染树的一部分)必须有一个我不知道的术语。
  • @user3808307,您可能是XY problem 的受害者。如果您可以描述一个合法的用例,当小部件变得不可见时(而不是在构建过程中,因为您可以在那里检查“已安装”),您希望回调的合法用例会很有帮助,那么我可以尝试进一步帮助您。
  • 我不想检查它何时变得不可见,而是在它变得不可见之前检查,以便将来自输入字段的数据存储在数据库中。通常需要知道小部件何时从树中删除,否则反应中不会有特定的功能。其他情况可能是取消订阅频道,例如
  • @user3808307 同样,“deactivate”是指从树中移除它的确切时间,而“dispose”通常是人们清理的地方,例如从频道取消订阅。如果我没记错的话,这些类似于 React 中的 useEffect return lambda。在您的示例中,屏幕 1 未卸载这一事实是完美的,因为您不想在这种情况下取​​消订阅,因此用户可以快速返回它。要存储输入字段,您应该在用户完成输入时(onSubmit 事件)、焦点被移除或每次更改时执行此操作。
  • 如果屏幕 1 没有卸载是完美的,那么 deactivate 不是我需要的。在这里您可以看到一个类似的问题,将其与 android 函数 stackoverflow.com/questions/44331725/… 而不是 react 函数进行比较
猜你喜欢
  • 2020-11-23
  • 1970-01-01
  • 1970-01-01
  • 2017-07-04
  • 1970-01-01
  • 2021-10-03
  • 1970-01-01
  • 2022-11-05
  • 1970-01-01
相关资源
最近更新 更多