Почему RiverPod StreamProvider зависает при загрузке, хотя Stream.empty() должен возвращаться, когда база данных имеет значение NULL

Я использую эту отличную стартовую архитектуру flutter / riverpod / firebase . На моем начальном флаттер-экране, который импортирует top_level_providers.dart то loading параметр - это все, что когда-либо вызывается.

В моем accountStreamProvider когда databaseProvider возвращает null Stream.empty() испускается, что в соответствии с документами «Это поток, который ничего не делает, кроме отправки события done, когда он прослушивается.».

Почему не data параметр, вызываемый в account.when раздел?

root_screen.dart

      class AppStartupScreenRouter extends ConsumerWidget {
  const AppStartupScreenRouter({
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context, ScopedReader watch) {
    final didCompleteOnboarding = watch(onboardingViewModelProvider.state);
    AsyncValue<Account> account = watch(accountStreamProvider);

    return account.when(
      data: (data) {
        if (data != null) {
          // evaluate the account info data and
          // return a screen widget
        } else if (didCompleteOnboarding) {
          // return a screen widget
        }

        return IntroScreen();
      },
      loading: () => LoadingScreen(),
      error: (err, stack) => EmptyContent(),
    );
  }
}

top_level_providers.dart

      final firebaseAuthProvider =
    Provider<FirebaseAuth>((ref) => FirebaseAuth.instance);

final authStateChangesProvider = StreamProvider<User>(
    (ref) => ref.watch(firebaseAuthProvider).authStateChanges());

final databaseProvider = Provider<FirestoreDatabase>((ref) {
  final auth = ref.watch(authStateChangesProvider);

  if (auth.data?.value?.uid != null) {
    return FirestoreDatabase(uid: auth.data?.value?.uid);
  }

  return null;
});

final accountStreamProvider = StreamProvider<Account>((ref) {
  final db = ref.watch(databaseProvider);
  return db != null ? db.accountStream() : Stream.empty();
});

firestore_database.dart

      class FirestoreDatabase {
  FirestoreDatabase({@required this.uid})
      : assert(
            uid != null, 'Cannot create FirestoreDatabase entry with null uid');
  final String uid;

  final _service = FirestoreService.instance;

  Future<void> setAccount(Account account) => _service.setData(
        path: FirestorePath.account(uid),
        data: account.toMap(),
      );

  Stream<Account> accountStream() => _service.documentStream(
        path: FirestorePath.account(uid),
        builder: (data, documentId) => Account.fromMap(data, uid),
      );

  Future<void> deleteAccount(Account account) =>
      _service.deleteData(path: FirestorePath.account(uid));
}

account.dart

      @immutable
class Account extends Equatable {
  const Account({
    @required this.id,
    @required this.firstName,
    @required this.lastName,
  });

  final String id;
  final String firstName;
  final String lastName;

  @override
  List<Object> get props => [
        id,
        firstName,
        lastName,
      ];

  @override
  bool get stringify => true;

  factory Account.fromMap(Map<String, dynamic> data, String documentId) {
    if (data == null) {
      return null;
    }

    final firstName = data['firstName'] as String;
    final lastName = data['lastName'] as String;

    if (firstName == null || lastName == null) {
      return null;
    }

    return Account(
      id: documentId,
      firstName: firstName,
      lastName: lastName,
    );
  }

  Map<String, dynamic> toMap() {
    return {
      'firstName': firstName,
      'lastName': lastName,
    };
  }
}

1 ответ

Stream.empty()никогда не содержит данных. Если это то, что ты StreamProviderвозвращается, обратный вызов не вызывается. Скорее всего вы получите loading Только.

Чтобы получить data обратного вызова, ваш поток должен возвращать хотя бы один элемент (неважно, нулевой он или нет).

Другие вопросы по тегам