如何在 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());
          },
        ),
      ),
    );
  }
}