Есть ли способ загрузить асинхронные данные по методу InitState?

Я ищу способ загрузки асинхронных данных по методу InitState, мне нужны некоторые данные перед запуском метода сборки. Я использую код GoogleAuth, и мне нужно выполнить метод сборки до запуска Stream.

Мой метод initState:

 @override
  void initState () {
    super.initState();
    _googleSignIn.onCurrentUserChanged.listen((GoogleSignInAccount account)     {
      setState(() {
        _currentUser = account;
      });
    });
    _googleSignIn.signInSilently();
  }

Буду признателен за любые отзывы.

Ответы

Ответ 1

Вы можете использовать StreamBuilder для этого. Это будет работать метод строитель всякий раз, когда данные в изменениях потока.

Ниже приведен фрагмент кода из одного из моих примерных проектов:

StreamBuilder<List<Content>> _getContentsList(BuildContext context) {
    final BlocProvider blocProvider = BlocProvider.of(context);
    int page = 1;
    return StreamBuilder<List<Content>>(
        stream: blocProvider.contentBloc.contents,
        initialData: [],
        builder: (context, snapshot) {
          if (snapshot.data.isNotEmpty) {
            return ListView.builder(itemBuilder: (context, index) {
              if (index < snapshot.data.length) {
                return ContentBox(content: snapshot.data.elementAt(index));
              } else if (index / 5 == page) {
                page++;
                blocProvider.contentBloc.index.add(index);
              }
            });
          } else {
            return Center(
              child: CircularProgressIndicator(),
            );
          }
        });
  }

В приведенном выше коде StreamBuilder прослушивает любое изменение содержимого, изначально его пустым массивом и показывает CircularProgressIndicator. После того, как я сделать вызов API данных надуманным добавляются содержимое массива, который будет работать метод строителя.

Когда пользователь прокручивает вниз, больше контента извлекается и добавляется к содержимому массива, который снова будет работать метод строитель.

В вашем случае потребуется только начальная загрузка. Но это дает вам возможность отображать что-то еще на экране, пока данные не будут извлечены.

Надеюсь, это полезно.

РЕДАКТИРОВАТЬ:

В вашем случае я предполагаю, что это будет выглядеть примерно так:

StreamBuilder<List<Content>>(
        stream: account, // stream data to listen for change
        builder: (context, snapshot) {
            if(account != null) {
                return _googleSignIn.signInSilently();
            } else {
                // show loader or animation
            }
        });

Ответ 2

Вы можете создать async метод и вызвать его внутри вашего initState

   @override
    void initState () {
      super.initState();
     _asyncMethod();
    }

    _asyncMethod() async {
     _googleSignIn.onCurrentUserChanged.listen((GoogleSignInAccount account)     {
        setState(() {
          _currentUser = account;
        });
      });
      _googleSignIn.signInSilently();
    }

Ответ 3

На данный момент использование .then нотация работает:

  // ...
  @override
  initState() {
    super.initState();
    asyncFunction.then((result) {
    print("result: $result");
    setState(() {});
    });
  }
  //...

Ответ 4

Вы можете установить логическое значение, такое как загруженный, и установить его в true в вашей функции прослушивания, и заставить вашу функцию сборки возвращать ваши данные, когда загруженное значение равно true, в противном случае просто бросьте CircularProgressIndicator.