Как установить индикатор загрузки, пока FutureProvider не выполнен

#flutter #dart #flutter-provider

Вопрос:

Я использую FutureProvider для извлечения данных из локальной базы данных с помощью SQflite, а затем отображаю график в дочернем элементе потребителя. Однако при загрузке приложения в течение короткого периода времени отображается ошибка :

 The following StateError was thrown building Consumer<List<Map<String, dynamic>>>(dirty,
                    dependencies: [_InheritedProviderScope<List<Map<String, dynamic>>>]):
                    Bad state: No element
 

После того, как график будет отрисован нормально.

Как я могу поймать это состояние загрузки, чтобы ошибка исчезла, и я мог показать CircularProgressIndicator() ?

Родитель

  FutureProvider<List<Map<String, dynamic>>>(
        create: (context) {
          return RecordsDatabase.instance.getRecords();
        },
        catchError: (context, error) {
          print("error: ${error.toString()}");
          return [];
        },
        initialData: [],
        child: HomeCustom(),
      )
 

Ребенок

 @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,
                ),
              ),
            )
          ]),
        ),
      );
    });
  }
}

 

Ответ №1:

В поле Consumer records сначала проверьте значение , а затем верните соответствующий виджет.

Образец…

 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 amp;amp;
                records.first.containsKey('error')) {
              return Text(records.first['error'] as String);
            }

            return Text(records.toString());
          },
        ),
      ),
    );
  }
}