简体   繁体   English

Flutter:在无状态小部件中“查找已停用小部件的祖先是不安全的”

[英]Flutter: “Looking up a deactivated widget's ancestor is unsafe” in a Stateless Widget

I am new to Flutter, and this problem really bothers me, I has searched through the Internet, however, none of the results satisfies me:我是Flutter的新手,这个问题真的很困扰我,我在网上搜索过,但是没有一个结果让我满意:

I try to use Progress Dialog from the package:我尝试使用 package 中的进度对话框:

import 'package:progress_dialog/progress_dialog.dart';

And the class MyApp in my main.dart file is like this:而我的main.dart文件中的class MyApp是这样的:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // Declare and decorate my Progress Dialog.
    ProgressDialog pr = ProgressDialog(
      context,
      type: ProgressDialogType.Normal,
      isDismissible: false,
    );
    pr.style(
      message: 'Fetching Something...',
      borderRadius: 50.0,
      elevation: 5.0,
    );

    // TODO: implement build method
    return MaterialApp(
      home: Scaffold(
        body: RaisedButton.icon(
          onPressed: () async {
            pr.show();
            await fetchData();
            pr.hide();
          },
          icon: Icon(Icons.clear),
          label: Text('Fetch Data'),
        ),
      ),
    );
  }
}

And my example fetchData() function is like this (of course the package and installation steps for Firestore's functions are validated):而我的示例fetchData() function 是这样的(当然 package 和 Firestore 功能的安装步骤已经过验证):

Future<void> fetchData() async {
  // Just an example of really fetching something.
  await Firestore.instance
      .collection('users')
      .document('0')
      .delete();
}

What I want is that, every time I click the button, a loading spinner is showed and hides immediately after fetchData() function finishes.我想要的是,每次单击按钮时,都会在fetchData() function 完成后立即显示和隐藏加载微调器。 This yields a correct flow in the first click, however, if I click the button for the second time, the spinner is not show (the fetchData() function still executes properly).这会在第一次单击时产生正确的流程,但是,如果我第二次单击该按钮,则不会显示微调器( fetchData() function 仍然可以正确执行)。 And a warning (not an error) is displayed in the Terminal:并在终端中显示警告(不是错误):

I/flutter (17942): Exception while showing the dialog
I/flutter (17942): Looking up a deactivated widget's ancestor is unsafe.
I/flutter (17942): At this point the state of the widget's element tree is no longer stable.
I/flutter (17942): To safely refer to a widget's ancestor in its dispose() method, save a reference to the ancestor by calling dependOnInheritedWidgetOfExactType() in the widget's didChangeDependencies() method.

The documents on dependOnInheritedWidgetOfExactType() are quite limited and difficult to understand.有关dependOnInheritedWidgetOfExactType()的文档非常有限且难以理解。 So I still have no idea of how to solve this problem correctly.所以我仍然不知道如何正确解决这个问题。

Any help is really appreciated.非常感谢任何帮助。 Thank you.谢谢你。

You can copy paste run full code below您可以在下面复制粘贴运行完整代码
You can use await pr.show();您可以使用await pr.show(); and await pr.hide();await pr.hide();
code snippet代码片段

onPressed: () async {
        await pr.show();
        await fetchData();
        await pr.hide();
      },

working demo工作演示

在此处输入图像描述

full code完整代码

import 'package:flutter/material.dart';
import 'package:progress_dialog/progress_dialog.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  Future<void> fetchData() async {
    await Future.delayed(Duration(seconds: 3), () {});
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    ProgressDialog pr = ProgressDialog(
      context,
      type: ProgressDialogType.Normal,
      isDismissible: false,
    );
    pr.style(
      message: 'Fetching Something...',
      borderRadius: 50.0,
      elevation: 5.0,
    );

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            RaisedButton.icon(
              onPressed: () async {
                await pr.show();
                await fetchData();
                await pr.hide();
              },
              icon: Icon(Icons.clear),
              label: Text('Fetch Data'),
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM