Flutter: “Looking up a deactivated widget’s ancestor is unsafe” in a Stateless Widget Code Answer

I am new to Flutter, and this problem really bothers me, I has searched through the Internet, however, none of the results satisfies me:

I try to use Progress Dialog from the package:

import 'package:progress_dialog/progress_dialog.dart';

And the class MyApp in my main.dart file is like this:

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):

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. 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). 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. So I still have no idea of how to solve this problem correctly.

Any help is really appreciated. Thank you.

Answer

You can copy paste run full code below
You can use await pr.show(); and await pr.hide();
code snippet

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

working demo

enter image description here

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),
      ),
    );
  }
}

Related Posts

© No Copyrights, All Questions are retrived from public domain.
Tutorial Guruji