5

I have got this piece of pop up Dialog() code in flutter https://gist.github.com/axilaris/2b186c7a4073671128e8cacc09dfc384, if you check out the code somewhere right at the bottom

class PurchaseDialog extends StatefulWidget with NavigationStates {
...
class _PurchaseDialogState extends State<PurchaseDialog> {
...
  @override
  Widget build(BuildContext context) {
    return Dialog(
...
 showSecondaryButton(BuildContext context) {
...
Navigator.of(context).pop(); <--- here is the problem

whenever it calls

Navigator.of(context).pop();

it will cause the following error

[ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: NoSuchMethodError: The method 'findAncestorStateOfType' was called on null.

this looks like a duplicate of this NoSuchMethodError: The method 'ancestorStateOfType' was called on null with await and async method, but i'ved tried the solutions it does not work. (context can only set once, and checking mounted variable have no effect).

How to resolve this ? So far it dismiss the dialog (with pop() so its correct behaviour), but I dont want this error coming out.

UPDATE info: The PurchaseDialog() above is called in this way:

    showDialog(
      context: context,
      builder: (BuildContext context) => PurchaseDialog(),
    ).then((value) {
      setState(() {
      });
    });

here are trace prints: https://gist.github.com/axilaris/6d8db8824b0b89e33fee7ddfdd238e34

Axil
  • 3,606
  • 10
  • 62
  • 136
  • If you're calling Navigator.of(context).pop(); it means there is a page before that, did you create a Material app at the beginning? Also you're calling pop a lot before creating dialogs in your methods, if you want to change dialog it's better to use pushReplacement – EdwynZN Jun 14 '20 at 16:34
  • not really, i updated info on PurchaseDialog() on how its called. – Axil Jun 15 '20 at 05:14
  • btw, I dont want to replace. its just a matter of dismissing the modaldialog. – Axil Jun 15 '20 at 05:18
  • I don't see you cancel the listeners FlutterInappPurchase.purchaseUpdated.listen or FlutterInappPurchase.purchaseError.listen when disposing the widget, you have a lot of Navigator.pop() and it's hard to follow the logic, if you setState in the showDialog after closing maybe it runs one of the listeners and call the pop, but the widget is disposed and thats why is null, do you have the stack trace or post the prints you have in your class to see where does it go when the error happens – EdwynZN Jun 15 '20 at 18:46
  • setState() is to refresh the view I believe. – Axil Jun 17 '20 at 00:59
  • Yeah setState does that, but what I was trying to say is if the FlutterInappPurchase is used in the previous page and the setState updates some stream listener that you don't close in the dialog, please post the whole stack trace and print to see if there is some other code running after "secondary button pressed" – EdwynZN Jun 17 '20 at 04:42
  • here you go: https://gist.github.com/axilaris/6d8db8824b0b89e33fee7ddfdd238e34 – Axil Jun 17 '20 at 22:08
  • 1
    canceling the listeners did the trick. I'll award the answer to you. Thanks _purchaseUpdatedSubscription.cancel(); _purchaseErrorSubscription.cancel(); – Axil Jun 17 '20 at 22:18

1 Answers1

2

After reading the trace prints we can be sure the problem was with FlutterInappPurchase.purchaseUpdated.listen(...) and FlutterInappPurchase.purchaseError.listen(...) that weren't disposed after the dialog was closed. They used the context to pop and open a new dialog (in the case of the purchaseError) which at that moment could be null. Canceling the streams after disposing the widget fixes the issue. Glad to know that fixes the problem

@override
void dispose(){
  super.dispose();
  _purchaseUpdatedSubscription.cancel();
  _purchaseErrorSubscription.cancel();
}
EdwynZN
  • 4,895
  • 2
  • 12
  • 15