I'm trying to delete data from firebase when user click the button.
await context
line is problematic!
class SecurityOption extends StatelessWidget {//StatelessWidget
const SecurityOption({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
children: [
Divider(
height: 3,
),
ListTile(
title: Text('security').tr(),
leading: Container(
height: 30,
width: 30,
decoration: BoxDecoration(
color: Colors.red, borderRadius: BorderRadius.circular(5)),
child: Icon(Feather.lock, size: 20, color: Colors.white),
),
trailing: Icon(
Feather.chevron_right,
size: 20,
),
onTap: () => _openDeleteDialog(context),
),
],
);
}
_openDeleteDialog(context) {
return showDialog(
barrierDismissible: true,
context: context,
builder: (context) {
return AlertDialog(
title: Text('Delete data').tr(),
content: Text('Are you sure?').tr(),
actions: [
TextButton(
onPressed: () async {
Navigator.pop(context);
await context //This line is problematic!
.read<SignInBloc>()
.deleteDatafromDatabase()
.then((_) async =>
await context.read<SignInBloc>().userSignout())
.then(
(_) => context.read<SignInBloc>().afterUserSignOut())
.then((_) {
Future.delayed(Duration(seconds: 1)).then((value) =>
nextScreenCloseOthers(context, WelcomePage()));
});
},
child: Text('YES').tr(),
),
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('cancel').tr())
],
);
});
}
}
SignInBloc Class:
class SignInBloc extends ChangeNotifier {
...
...
...
Future deleteDatafromDatabase () async{
FirebaseFirestore _db = FirebaseFirestore.instance;
await _db.collection('x').doc('y').delete();
}
}
When I run the app & click the button, it deletes the data but gives an error.
Exception has occurred.
FlutterError (Looking up a deactivated widget's ancestor is unsafe. At this point the state of the widget's element tree is no longer stable. 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.)
Besides, the app is freezing(is not closing). Clicks, swipes, etc. is not working...
How can I solve my problem?
You have identified correctly the problematic code.
The problem is after you pop the Dialog, the dialog's context no longer exists but you are trying to access it.
It is almost always better to not use the context that the Dialog builder provides because it can be dismissed at anytime. Even if you move the Navigator.pop to the end you have the barrierDismissible: true
so the dialog can be dismissed and you will not be able to access the context.
You can solve this issue by:
dialogContext
and use this to pop Navigator.pop(dialogContext)
and use the context
passed to the _openDeleteDialog
for the next operations._openDeleteDialog(context) {
return showDialog(
barrierDismissible: true,
context: context,
builder: (dialogContext) { <------- Change this
return AlertDialog(
title: Text('Delete data').tr(),
content: Text('Are you sure?').tr(),
actions: [
TextButton(
onPressed: () async {
Navigator.pop(dialogContext); <----- Use here
await context <--- Keep as is
.read<SignInBloc>()
.deleteDatafromDatabase()
.then((_) async =>
await context.read<SignInBloc>().userSignout())
.then(
(_) => context.read<SignInBloc>().afterUserSignOut())
.then((_) {
Future.delayed(Duration(seconds: 1)).then((value) =>
nextScreenCloseOthers(context, WelcomePage()));
});
},
child: Text('YES').tr(),
),
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('cancel').tr())
],
);
});
}
_openDeleteDialog
and call it after the Navigator.pop
.onTap: () => _openDeleteDialog(context, ()async {
await context
.read<SignInBloc>()
.deleteDatafromDatabase()
.then((_) async =>
await context.read<SignInBloc>().userSignout())
.then(
(_) => context.read<SignInBloc>().afterUserSignOut())
.then((_) {
Future.delayed(Duration(seconds: 1)).then((value) =>
nextScreenCloseOthers(context, WelcomePage()));
});
}
),
_openDeleteDialog(context, VoidCallback onDelete) {
return showDialog(
barrierDismissible: true,
context: context,
builder: (context) {
return AlertDialog(
title: Text('Delete data').tr(),
content: Text('Are you sure?').tr(),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
onDelete();
},
child: Text('YES').tr(),
),
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('cancel').tr())
],
);
});
}