Почему 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
обратного вызова, ваш поток должен возвращать хотя бы один элемент (неважно, нулевой он или нет).