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