skip to Main Content

Flutter gives me the warning "Don’t use ‘BuildContext’s across async gaps. Try rewriting the code to not use the ‘BuildContext’, or guard the use with a ‘mounted’ check". The warning is in my app twice and I can’t make any of them go away by adding a "mounted guard". Below is a full standalone app that demonstrates a simple version of my app. Can you please show me what is the ideal way of solving this problem, and if it’s the "mounted guard", where should I put them?

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

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Search History Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Search History'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            clearEnglishHistory(context);
          },
          child: const Text('Clear History'),
        ),
      ),
    );
  }

  Future<void> clearEnglishHistory(BuildContext context) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    bool confirmClear = await showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: const Text('Confirmation'),
          content: const Text('Do you really want to clear search history?'),
          actions: <Widget>[
            TextButton(
              onPressed: () {
                Navigator.of(context).pop(false);
              },
              child: const Text('No'),
            ),
            TextButton(
              onPressed: () {
                Navigator.of(context).pop(true);
              },
              child: const Text('Yes'),
            ),
          ],
        );
      },
    );

    if (confirmClear == true) {
      await prefs.remove('english history');
      ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
        content: Text('History cleared'),
      ));
    }
  }
}

2

Answers


  1. you need to either disable the message using lint message, or you can add a mounted check before you show your snackbar. Something like this:

    if (confirmClear == true) {
          await prefs.remove('english history');
          if(!mounted) return;
          ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
            content: Text('History cleared'),
          ));
        }
    
    
    Login or Signup to reply.
  2. Others have answered where to add the mounted guard, but I wanted to point out that

    await SharedPreferences.getInstance()
    

    should really appear only in your main, saving the result into a global prefs var. Once you get the instance, you have the instance, and you can use it totally synchronously to get values as well. The only async you’ll need to worry about then is the writing of new values, and even that can be fire-and-forget for the most part.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search