Flutter 在InitState未处理异常中显示对话框:查找已停用的小部件';他的祖先是不安全的
第一次出现屏幕时,我想检查用户GPS是否启用,位置权限是否授予。然后,如果其中一个未实现,我将显示对话框以打开应用程序设置 源代码 然后我在initState中调用了这个函数,如下所示: 初始状态 问题是,每次屏幕出现时,都会出现如下错误: 错误 我所做的:Flutter 在InitState未处理异常中显示对话框:查找已停用的小部件';他的祖先是不安全的,flutter,Flutter,第一次出现屏幕时,我想检查用户GPS是否启用,位置权限是否授予。然后,如果其中一个未实现,我将显示对话框以打开应用程序设置 源代码 然后我在initState中调用了这个函数,如下所示: 初始状态 问题是,每次屏幕出现时,都会出现如下错误: 错误 我所做的: 像这样改变你的状态 为Scaffold添加全局键 final GlobalKey _scaffoldKey=GlobalKey(); 脚手架( 钥匙:_scaffoldKey, 寻找与我相似的问题 我所做的结果是什么都
- 像这样改变你的状态
- 为Scaffold添加全局键
final GlobalKey _scaffoldKey=GlobalKey();
脚手架(
钥匙:_scaffoldKey,
- 寻找与我相似的问题
Future.delayed(Duration(milliseconds: 50)).then((_) => _initPermission(context));
到
该错误在热重启中消失,因为它只是刷新小部件的状态,但它已经被创建(如果您在initState中执行热重启并打印某些内容,例如print('This is init');您也不会看到它,因为刷新不会处理和初始化小部件,因此它不会再次运行该代码段)
编辑
根据你的要点,我刚刚制作了一个最小的可复制示例,在DartPad中运行时没有问题,稍后我将在VS上尝试,但现在你能检查一下是否有什么不同吗
enum GeolocationStatus{granted, denied} //this is just for example
class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
showPermissionGPS() {
return AlertDialog(
title: Text('GPSStatus'),
);
}
_showPermissionLocation() {
return AlertDialog(
title: Text('Permission Localization'),
);
}
@override
initState(){
super.initState();
Future.delayed(Duration(milliseconds: 50)).then((_) => _initPermission());
}
_initPermission() async{
final geolocationStatus = await Future<GeolocationStatus>.value(GeolocationStatus.granted); //mocked future with a response to test
final gpsStatus = await Future<bool>.value(false); //mocked future with a response to test
if (geolocationStatus != GeolocationStatus.granted) {
await showDialog(
context: context,
builder: (ctx) => _showPermissionLocation() //this mock commonF.showPermissionLocation and returns an AlertDialog
);
} else if (!gpsStatus) {
await showDialog(
context: context,
builder: (ctx) => _showPermissionGPS() //this mock commonF.showPermissionGPS and returns an AlertDialog
);
}
}
@override
Widget build(BuildContext context) {
return Text('My text');
}
}
enumgeolocationstatus{grated,denied}//这只是一个例子
类MyWidget扩展了StatefulWidget{
@凌驾
_MyWidgetState createState()=>\u MyWidgetState();
}
类_MyWidgetState扩展状态{
showPermissionGPS(){
返回警报对话框(
标题:文本(“GPSStatus”),
);
}
_showPermissionLocation(){
返回警报对话框(
标题:文本(“权限本地化”),
);
}
@凌驾
initState(){
super.initState();
Future.delayed(持续时间(毫秒:50))。然后(()=>_initPermission());
}
_initPermission()异步{
final geolocationStatus=await Future.value(geolocationStatus.grated);//模拟未来并响应测试
final gpsStatus=await Future.value(false);//模拟未来并响应测试
if(geolocationStatus!=geolocationStatus.grated){
等待显示对话框(
上下文:上下文,
生成器:(ctx)=>\u showPermissionLocation()//此模拟commonF.showPermissionLocation并返回AlertDialog
);
}否则如果(!gpsStatus){
等待显示对话框(
上下文:上下文,
生成器:(ctx)=>\u showPermissionGPS()//此模拟commonF.showPermissionGPS并返回AlertDialog
);
}
}
@凌驾
小部件构建(构建上下文){
返回文本(“我的文本”);
}
}
已尝试此操作,它将产生新的错误'context!=null':不正确。
错误将指定为initState
和showDialog
commonF是从哪个包来的?commonF
是我存储在一个文件中的所有分离函数。commonF.showPermissionGPS和commonF.showPermissionLocation如何?这些是吗返回小部件的方法?我编辑了对话框的答案以返回ctx,我更新了要点,使其更加清晰。showPermissionGPS
&showPermissionLocation
it return alertDialog。可在此处查看
[ERROR:flutter/lib/ui/ui_dart_state.cc(166)] Unhandled Exception: 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.
//1
WidgetsBinding.instance.addPostFrameCallback((_) {
_initPermission(context);
});
//2
SchedulerBinding.instance.addPostFrameCallback((_) => _initPermission(context));
//3
Timer.run(() {
_initPermission(context);
})
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
Scaffold(
key: _scaffoldKey,
Future.delayed(Duration(milliseconds: 50)).then((_) => _initPermission(context));
Future.delayed(Duration(milliseconds: 50)).then((_) => _initPermission()); //this inside the initstate
_initPermission() async{
final geolocationStatus = await commonF.getGeolocationPermission();
final gpsStatus = await commonF.getGPSService();
if (geolocationStatus != GeolocationStatus.granted) {
await showDialog(
context: context,
builder: (ctx) => commonF.showPermissionLocation
},
);
} else if (!gpsStatus) {
await showDialog(
context: context,
builder: (ctx) => commonF.showPermissionGPS
},
);
}
} // the stateful widget can use the context in all its methods without passing it as a parameter
enum GeolocationStatus{granted, denied} //this is just for example
class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
showPermissionGPS() {
return AlertDialog(
title: Text('GPSStatus'),
);
}
_showPermissionLocation() {
return AlertDialog(
title: Text('Permission Localization'),
);
}
@override
initState(){
super.initState();
Future.delayed(Duration(milliseconds: 50)).then((_) => _initPermission());
}
_initPermission() async{
final geolocationStatus = await Future<GeolocationStatus>.value(GeolocationStatus.granted); //mocked future with a response to test
final gpsStatus = await Future<bool>.value(false); //mocked future with a response to test
if (geolocationStatus != GeolocationStatus.granted) {
await showDialog(
context: context,
builder: (ctx) => _showPermissionLocation() //this mock commonF.showPermissionLocation and returns an AlertDialog
);
} else if (!gpsStatus) {
await showDialog(
context: context,
builder: (ctx) => _showPermissionGPS() //this mock commonF.showPermissionGPS and returns an AlertDialog
);
}
}
@override
Widget build(BuildContext context) {
return Text('My text');
}
}