Home > database >  Flutter: Optional AlertDialog when opening the app
Flutter: Optional AlertDialog when opening the app

Time:10-23

I'm trying to have an alertDialog displayed when opening my app (that: it works) and I would like to have a boolean as an option (with shared preferences) to propose not to display the message when opening . What is my mistake?

my boolean and my initState:

  late bool _alertMessage = true;

    @override
      void initState() {
        super.initState();
        retrieveBoolData();
        alertMessageAppOpen();
      }

my shared preferences settings:

    Future<void> addBoolData() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    _alertMessage = false;
    setState(() {
      prefs.setBool('alertbool', false);
    });
  }
  

Future<void> retrieveBoolData() async {
        SharedPreferences prefs = await SharedPreferences.getInstance();
        setState(() {
          _alertMessage = prefs.getBool('alertbool')!;
        });
      }

My Alert dialog :

    void alertMessageAppOpen()  {
    return
      _alertMessage == false
          ? null
          : WidgetsBinding.instance.addPostFrameCallback((_) async {
        await showDialog<String>(
          context: context,
          builder: (BuildContext context) => AlertDialog(
            backgroundColor: Colors.white,
            title: const Text('Alert !',
              style: TextStyle(color:  Colors.black54),
            ),
            actions: <Widget>[
              TextButton(
                child: const Text('do not display anymore',
                  style: TextStyle(color: Colors.white),
                ),
                onPressed: () {
                  setState(() {
                    _alertMessage == false;
                    addBoolData();
                  });
                  Navigator.of(context).pop();
                },
              ),
              TextButton(
                child: const Text('OK',
                  style: TextStyle(color: Colors.white),
                ),
                onPressed: () {
                  Navigator.of(context).pop();
                },
              ),
            ],
          ),
        );
      });
  }

CodePudding user response:

since your function is Future, you have to use await

onPressed: () async {
  await addBoolData();
  Navigator.of(context).pop();
},

CodePudding user response:

I don't no if is the good method...

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


class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  late bool _alertMessage = true;

  @override
  Widget build(BuildContext context) {

    return FutureBuilder<bool>(
      future: retrieveBoolData(),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.done && !snapshot.hasError) {
          _alertMessage = snapshot.data?? true;
          alertMessageAppOpen();
        }
        return Scaffold(
            appBar: AppBar(
              title: const Text('Test Alert'),
              actions: [
                IconButton(
                  icon: const Icon(Icons.power_settings_new),
                  color: Colors.white,
                  onPressed: () {
                    SystemNavigator.pop();
                    exit(0);
                  },
                )
              ],
            ),
            body:  Center(
              child:
              _alertMessage == true
                  ? const Text('bool saved = true')
                  : const Text('bool saved = false'),
            )
        );
      },
    );
  }

  /// SHARED PREFERENCIES
  Future<void> addBoolData() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
      prefs.setBool('alertbool', _alertMessage);
  }
  Future<bool> retrieveBoolData() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    bool? result = prefs.getBool('alertbool');
    if(result != null){
      return result;
    }
    return true;
  }
  /// ALERT DIALOG AT THE OPENING APP
  void alertMessageAppOpen()  {
    return WidgetsBinding.instance.addPostFrameCallback((_) async {
      await showDialog<String>(
        context: context,
        builder: (BuildContext context) => AlertDialog(
          backgroundColor: Colors.white,
          title: const Text('Alert !',
            style: TextStyle(color:  Colors.black54),
          ),
          actions: <Widget>[
            TextButton(
              child: const Text('do not display anymore',
                style: TextStyle(color: Colors.red),
              ),
              onPressed: () async {
                _alertMessage = false;
                await addBoolData();
                Navigator.of(context).pop();
              },
            ),
            TextButton(
              child: const Text('OK',
                style: TextStyle(color: Colors.blue),
              ),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
          ],
        ),
      );
    });
  }
}

CodePudding user response:

First it is wrong to call async inside initState, you need to use FutureBuilder. So change your retrieveBoolData to this:

Future<bool> retrieveBoolData() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    bool? result = prefs.getBool('alertbool');
    if(result != null){
      return result;
    }
    return true;
  }

then inside your builder method wrap your widget with FutureBuilder:

return FutureBuilder<bool>(
          future: retrieveBoolData(),
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.done && !snapshot.hasError) {
              _alertMessage = snapshot.data?? true;
              alertMessageAppOpen();
            }

            return your rest of your widget 
          },
        ),

then inside your alertMessageAppOpen() you don't need to call setState and also need to await for addBoolData() result then pop to previous screen and also you pass _alertMessage's value wrong, don't use ==:

onPressed: () async {
  _alertMessage = false;
  await addBoolData();
  Navigator.of(context).pop();
},

you also need to delete initState you don't need it any more and change addBoolData this:

Future<void> addBoolData() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setBool('alertbool', _alertMessage);
  }

the full example:

class TestingDesign2 extends StatefulWidget {
  const TestingDesign2({super.key});

  @override
  State<TestingDesign2> createState() => _TestingDesign2State();
}

class _TestingDesign2State extends State<TestingDesign2> {

  late bool _alertMessage = true;

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<bool>(
      future: retrieveBoolData(),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.done &&
            !snapshot.hasError) {
          _alertMessage = snapshot.data ?? true;
          alertMessageAppOpen();
        }

        return Scaffold(
            appBar: AppBar(
              title: const Text('Test Alert'),
              actions: [
                IconButton(
                  icon: const Icon(Icons.power_settings_new),
                  color: Colors.white,
                  onPressed: () {
                    SystemNavigator.pop();
                    exit(0);
                  },
                )
              ],
            ),
            body: Center(
              child: _alertMessage == true
                  ? const Text('bool saved = true')
                  : const Text('bool saved = false'),
            ));
      },
    );
  }

  Future<bool> retrieveBoolData() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    bool? result = prefs.getBool('alertbool');
    if (result != null) {
      return result;
    }
    return true;
  }

  Future<void> addBoolData() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setBool('alertbool', _alertMessage);
  }

  void alertMessageAppOpen() {
    return _alertMessage == false
        ? null
        : WidgetsBinding.instance.addPostFrameCallback((_) async {
            await showDialog<String>(
              context: context,
              builder: (BuildContext context) => AlertDialog(
                backgroundColor: Colors.white,
                title: const Text(
                  'Alert !',
                  style: TextStyle(color: Colors.black54),
                ),
                actions: <Widget>[
                  TextButton(
                    child: const Text(
                      'do not display anymore',
                      style: TextStyle(color: Colors.black),
                    ),
                    onPressed: () async {
                      _alertMessage = false;
                      await addBoolData();
                      Navigator.of(context).pop();
                    },
                  ),
                  TextButton(
                    child: const Text(
                      'OK',
                      style: TextStyle(color: Colors.black),
                    ),
                    onPressed: () {
                      Navigator.of(context).pop();
                    },
                  ),
                ],
              ),
            );
          });
  }
}
  • Related