如何在 FutureProvider 未完成时设置加载指示器
How to set a loading indicator while FutureProvider is not done
我正在使用 FutureProvider 通过 SQflite 从本地数据库获取数据,然后在 Consumer child 中呈现图形。但是,在加载应用程序时,会在短时间内显示错误:
The following StateError was thrown building Consumer<List<Map<String, dynamic>>>(dirty,
dependencies: [_InheritedProviderScope<List<Map<String, dynamic>>>]):
Bad state: No element
图形渲染正常后。
如何捕获此加载状态以使错误消失并显示 CircularProgressIndicator()?
Parent
FutureProvider<List<Map<String, dynamic>>>(
create: (context) {
return RecordsDatabase.instance.getRecords();
},
catchError: (context, error) {
print("error: ${error.toString()}");
return [];
},
initialData: [],
child: HomeCustom(),
)
Child
@override
Widget build(BuildContext context) {
return Consumer<List<Map<String, dynamic>>>(
builder: (context, records, child) {
GraphState graph =GraphState(records: records, context: context);
return ChangeNotifierProvider<GraphState>(
create: (_) => graph,
child: Scaffold(
backgroundColor: Colors.black,
body: Stack(children: [
Center(
child: graph.records.isEmpty
? Text(
'No Records',
style: TextStyle(color: Colors.white, fontSize: 24),
)
: MyGraph()),
Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.only(right: 30, bottom: 50),
child: FloatingActionButton(
child: Icon(Icons.add),
onPressed: _setVisible,
),
),
)
]),
),
);
});
}
}
在 Consumer
中,首先检查 records
值,然后 return 适当的小部件。
示例...
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: FutureProvider<List<Map<String, dynamic>>?>(
create: (_) => _getRecords(),
initialData: null,
catchError: (_, __) => <Map<String, dynamic>>[
{'error': 'Something went wrong'}
],
child: HomePage(),
),
);
}
Future<List<Map<String, dynamic>>> _getRecords() async {
final bool isError = false; // set to "true" to check error case
await Future<void>.delayed(const Duration(seconds: 5));
if (isError) {
throw Exception();
}
return <Map<String, dynamic>>[
<String, int>{'item': 1},
<String, String>{'itemTxt': 'one'},
];
}
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Consumer<List<Map<String, dynamic>>?>(
builder: (_, List<Map<String, dynamic>>? records, __) {
if (records == null) {
return const CircularProgressIndicator();
} else if (records.isNotEmpty &&
records.first.containsKey('error')) {
return Text(records.first['error'] as String);
}
return Text(records.toString());
},
),
),
);
}
}
我正在使用 FutureProvider 通过 SQflite 从本地数据库获取数据,然后在 Consumer child 中呈现图形。但是,在加载应用程序时,会在短时间内显示错误:
The following StateError was thrown building Consumer<List<Map<String, dynamic>>>(dirty,
dependencies: [_InheritedProviderScope<List<Map<String, dynamic>>>]):
Bad state: No element
图形渲染正常后。
如何捕获此加载状态以使错误消失并显示 CircularProgressIndicator()?
Parent
FutureProvider<List<Map<String, dynamic>>>(
create: (context) {
return RecordsDatabase.instance.getRecords();
},
catchError: (context, error) {
print("error: ${error.toString()}");
return [];
},
initialData: [],
child: HomeCustom(),
)
Child
@override
Widget build(BuildContext context) {
return Consumer<List<Map<String, dynamic>>>(
builder: (context, records, child) {
GraphState graph =GraphState(records: records, context: context);
return ChangeNotifierProvider<GraphState>(
create: (_) => graph,
child: Scaffold(
backgroundColor: Colors.black,
body: Stack(children: [
Center(
child: graph.records.isEmpty
? Text(
'No Records',
style: TextStyle(color: Colors.white, fontSize: 24),
)
: MyGraph()),
Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.only(right: 30, bottom: 50),
child: FloatingActionButton(
child: Icon(Icons.add),
onPressed: _setVisible,
),
),
)
]),
),
);
});
}
}
在 Consumer
中,首先检查 records
值,然后 return 适当的小部件。
示例...
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: FutureProvider<List<Map<String, dynamic>>?>(
create: (_) => _getRecords(),
initialData: null,
catchError: (_, __) => <Map<String, dynamic>>[
{'error': 'Something went wrong'}
],
child: HomePage(),
),
);
}
Future<List<Map<String, dynamic>>> _getRecords() async {
final bool isError = false; // set to "true" to check error case
await Future<void>.delayed(const Duration(seconds: 5));
if (isError) {
throw Exception();
}
return <Map<String, dynamic>>[
<String, int>{'item': 1},
<String, String>{'itemTxt': 'one'},
];
}
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Consumer<List<Map<String, dynamic>>?>(
builder: (_, List<Map<String, dynamic>>? records, __) {
if (records == null) {
return const CircularProgressIndicator();
} else if (records.isNotEmpty &&
records.first.containsKey('error')) {
return Text(records.first['error'] as String);
}
return Text(records.toString());
},
),
),
);
}
}