Как я должен использовать FirebaseAuth.instance.onAuthStateChanged в моем приложении флаттера? - PullRequest
0 голосов
/ 07 марта 2020

В моем приложении флаттера я пытаюсь передать пользовательский объект Firebase нисходящим виджетам, используя ChangeNotifier из пакета Provider. Моя первая идея заключалась в том, чтобы сделать это в StreamBuilder следующим образом:

  Widget _authBuilder(context, Widget body) {
    final authModel = Provider.of<FAAuthModel>(context);


    return StreamBuilder(
      stream: FirebaseAuth.instance.onAuthStateChanged,
      builder: (context, snapshot) {

        authModel.user = snapshot.data;

        return body;
      },
    );
  }

Единственная проблема заключается в том, что, очевидно, функция компоновщика работает асинхронно, пока создается виджет тела, и поэтому состояние помечается как грязное одновременно. , Есть ли более умный способ передачи FirebaseUser в нисходящее дерево виджетов?

I/flutter (28504): ══╡ EXCEPTION CAUGHT BY FOUNDATION LIBRARY ╞════════════════════════════════════════════════════════
I/flutter (28504): The following assertion was thrown while dispatching notifications for FAAuthModel:
I/flutter (28504): setState() or markNeedsBuild() called during build.
I/flutter (28504): This _DefaultInheritedProviderScope<FAAuthModel> widget cannot be marked as needing to build because
I/flutter (28504): the framework is already in the process of building widgets.  A widget can be marked as needing to
I/flutter (28504): be built during the build phase only if one of its ancestors is currently building. This exception
I/flutter (28504): is allowed because the framework builds parent widgets before children, which means a dirty
I/flutter (28504): descendant will always be built. Otherwise, the framework might not visit this widget during this
I/flutter (28504): build phase.
I/flutter (28504): The widget on which setState() or markNeedsBuild() was called was:
I/flutter (28504):   _DefaultInheritedProviderScope<FAAuthModel>
I/flutter (28504): The widget which was currently being built when the offending call was made was:
I/flutter (28504):   StreamBuilder<FirebaseUser>
I/flutter (28504): 

1 Ответ

0 голосов
/ 08 марта 2020

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

  Widget _authBuilder(context, Widget body) {
    Stream<FirebaseUser> stream;
    final authModel = Provider.of<FAAuthModel>(context);

    stream = FirebaseAuth.instance.onAuthStateChanged;

    stream.listen((snapshot) {

      /* We are not logged in */
      if (snapshot == null && authModel.user == null) {
         //Do nothing
      }
      /* We are not logged in, or we are logging out */
      else if (snapshot == null) {
        authModel.user = null;
        /* We are logged in but we just opened our app */
      } else if (authModel.user == null) {
        authModel.user = snapshot;
        /* We are logged in but something happened e.g. the widget tree was rebuilt and we just logged out? */
      } else if (authModel.user.uid != snapshot.uid) {
        authModel.user = snapshot;
      }
    });

    return body;
  }

...