Dra*_*ent 12 android dart flutter
我知道已经有两篇关于这个问题的帖子,但我无法解决我的问题。可能是因为在我的情况下,问题是不同的。
代码如下。我想在显示加载页面的同时从数据库加载一些数据。加载数据后,我使用加载的数据初始化提供程序,然后进入不同的页面。这段代码不需要放在StatefulWidget中,但我尝试将其放在StatefulWidget中来解决问题,但没有成功。
class _InitDBDataState extends State<_InitDBData> {
@override
Widget build(BuildContext context) {
_fetchData(context);
return const Center(child: const CircularProgressIndicator());
}
Future<void> _fetchData(BuildContext context) async {
print('fetching data...');
print('context: $context');
final initData = await DBService.service.getInitialData();
print('Data fetched');
print('context: $context');
Provider.of<DataProvider>(context, listen: false).init(initData);
Navigator.of(context).pushReplacementNamed(MainScreen.routeName);
}
}
Run Code Online (Sandbox Code Playgroud)
如果应用程序从头开始运行,我没有任何错误,但是当我执行“热重载”时,我经常收到以下错误,这很烦人,因为我需要为代码中的每个小更改重新启动应用程序。
I/flutter ( 9596): fetching data...
I/flutter ( 9596): context: _InitDBData(dirty, state: _InitDBDataState#46860)
I/flutter ( 9596): fetching data...
I/flutter ( 9596): context: _InitDBData(dirty, state: _InitDBDataState#55124)
I/flutter ( 9596): Data fetched
I/flutter ( 9596): context: _InitDBData
E/flutter ( 9596): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: Looking up a deactivated widget's ancestor is unsafe.
E/flutter ( 9596): At this point the state of the widget's element tree is no longer stable.
E/flutter ( 9596): 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.
E/flutter ( 9596): #0 Element._debugCheckStateIsActiveForAncestorLookup.<anonymous closure>
package:flutter/…/widgets/framework.dart:3508
E/flutter ( 9596): #1 Element._debugCheckStateIsActiveForAncestorLookup
package:flutter/…/widgets/framework.dart:3522
E/flutter ( 9596): #2 Element.getElementForInheritedWidgetOfExactType
package:flutter/…/widgets/framework.dart:3588
E/flutter ( 9596): #3 Provider.of
package:provider/src/provider.dart:221
E/flutter ( 9596): #4 _InitDBDataState._fetchData
package:productive_diary/initScreen.dart:46
E/flutter ( 9596): <asynchronous suspension>
E/flutter ( 9596): #5 _InitDBDataState.build
Run Code Online (Sandbox Code Playgroud)
我不知道为什么“获取数据...”会打印两次,我也不知道如何解决这个问题。
我认为这个问题已经通过Saman Salehi的解决方案解决了,但是在调试模式下我在 _fetchData 函数中有同样的异常,现在在函数initState() 中调用
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.)
Run Code Online (Sandbox Code Playgroud)
在应用Stewie Griffin 建议的编辑后,我又遇到了另一个错误。
错误就行了 Provider.of<DataProvider>(context, listen: false).init(initData);
我是在热重载期间得到的。似乎没有其他错误那么常见,所以 Stewie Griffin 的回答肯定提高了我Stewie Griffin 的稳定性
E/flutter (23815): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: NoSuchMethodError: The getter 'owner' was called on null.
E/flutter (23815): Receiver: null
E/flutter (23815): Tried calling: owner
E/flutter (23815): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
E/flutter (23815): #1 Provider.of
package:provider/src/provider.dart:193
E/flutter (23815): #2 _InitDBDataState._fetchData
package:productive_diary/initScreen.dart:49
E/flutter (23815): <asynchronous suspension>
E/flutter (23815): #3 _InitDBDataState.initState
Run Code Online (Sandbox Code Playgroud)
请你帮助我好吗?
Ste*_*wie 34
首先,永远不要像上面提到的那样在 build 内部调用异步方法。Build 方法会不断重建,它会导致您的 fetch 方法像无限循环一样重复。修复后,由于这部分,您仍然会遇到相同的错误:
Navigator.of(context).pushReplacementNamed(MainScreen.routeName);
您不应该在构建期间调用 Navigator。以下是您需要做的:
将此行添加到文件顶部以使用SchedulerBinding:
import 'package:flutter/scheduler.dart';
Run Code Online (Sandbox Code Playgroud)
使用 SchedulerBinding 包装 Navigator 以等待完成状态,然后再导航到另一个屏幕。然后,在initState.
class _InitDBDataState extends State<_InitDBData> {
@override
void initState() {
// Call your async method here
_fetchData();
super.initState();
}
Future<void> _fetchData() async {
print('fetching data...');
print('context: $context');
final initData = await DBService.service.getInitialData();
print('Data fetched');
print('context: $context');
Provider.of<DataProvider>(context, listen: false).init(initData);
// Wrap Navigator with SchedulerBinding to wait for rendering state before navigating
SchedulerBinding.instance.addPostFrameCallback((_) {
Navigator.of(context).pushReplacementNamed(MainScreen.routeName);
});
}
@override
Widget build(BuildContext context) {
return Center(child: CircularProgressIndicator());
}
}
Run Code Online (Sandbox Code Playgroud)
提示:您不需要在有状态小部件中传递上下文,因为您可以从任何地方访问它。
build除了构建 UI 之外,您不应该将该方法用于任何其他用途。build即使不在屏幕上,也可以随时调用。
我会将 移至_fetchData,initState这样就不会在该build方法中造成任何冲突。
class _InitDBDataState extends State<_InitDBData> {
@override
void initState() {
super.initState();
_fetchData(context);
}
@override
Widget build(BuildContext context) {
return const Center(child: const CircularProgressIndicator());
}
Future<void> _fetchData(BuildContext context) async {
print('fetching data...');
print('context: $context');
final initData = await DBService.service.getInitialData();
print('Data fetched');
print('context: $context');
Provider.of<DataProvider>(context, listen: false).init(initData);
Navigator.of(context).pushReplacementNamed(MainScreen.routeName);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
17347 次 |
| 最近记录: |