Flutter: Can't get StreamProvider to intentionally produce a null value

Issue

I’m using a StreamProvider, which is given a value by a Firestore Stream. It initially starts out producing null, as expected. The stream is then updated to start producing values from a valid Firestore document, and the stream provider does too, as expected.

I then have a user action, which then should stop reading the Firestore document and give a null value to the stream/streamprovider and notify listeners that the stream now has a null value. It doesn’t do this, and instead just keeps streaming the last-known non-null values. Stepping through the code, I see that databaseService.gameStream is called with a null input at the user action, as expected, but then the output from the StreamProvider doesn’t change to null as the code specifies.

Is anyone able to see what I’m missing?

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [ChangeNotifierProvider(create: (context) => AppUser())],
      child: InnerProviderClass(),
    );
  }
}

class InnerProviderClass extends StatelessWidget {
  final databaseService = DatabaseService();
  @override
  Widget build(BuildContext context) {
    AppUser appUser = Provider.of<AppUser>(context);
    return MultiProvider(
      providers: [
        StreamProvider<Game>.value(
          value: databaseService.gameStream(appUser.getCode),
          initialData: null,
          catchError: (_, err) {
            print(err);
            return null;
          },
        ),
      ],
      child: MaterialApp(
        navigatorKey: navigatorKey,
        title: 'Game',
        home: RouterNavigator(),
      ),
    );
  }
}

class DatabaseService {
  Stream<Game> gameStream(String gameCode) {
    return (gameCode != null)
        ? FirebaseFirestore.instance
            .collection('games')
            .doc(gameCode)
            .snapshots()
            .map((doc) => Game.fromDocument(doc))
        : null;
  }
}```

Solution

I was able to get this properly working by changing the segment in the above code to this:

class DatabaseService {
  Stream<Game> gameStream(String gameCode) {
    return (gameCode != null)
        ? FirebaseFirestore.instance
            .collection('games')
            .doc(gameCode)
            .snapshots()
            .map((doc) => Game.fromDocument(doc))
        : Stream<Game>.value(null);
   }
}

Stream<Game>.value(null); was the line changed.

Answered By – SofAllTrades

Answer Checked By – David Goodson (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published.