Provider: StreamProvider not providing update where StreamBuilder does

Created on 2 Apr 2020  路  4Comments  路  Source: rrousselGit/provider

First of all, thanks for this amazing package!

Can't get my head around this issue:

return StreamBuilder<UserWorkout>(
  stream: UserWorkouts().streamSingle(userId, workoutId),
  builder: (context, snapshot) {
    if (snapshot.connectionState != ConnectionState.active) {
      return Splash();
    }
    UserWorkout userWorkout = snapshot.data;
    if (userWorkout == null) {
      return Splash();
    }
    LogService.log('StreamBuilder<UserWorkout>_${userWorkout.id}');
    return child;
  },
);

Versus

return StreamProvider<UserWorkout>(
  create: (_) => UserWorkouts().streamSingle(userId, workoutId),
  updateShouldNotify: (_, __) => true,
  child: Consumer<UserWorkout>(
    builder: (context, UserWorkout userWorkout, _) {
      if (userWorkout == null) {
        return Splash();
      }
      LogService.log('Consumer<UserWorkout>_${userWorkout.id}');
      return child;
    },
  ),
);

First code block works by providing an updated userWorkout object when a new userId/workoutId has been supplied. When I supply new parameters, I can see that the stream emits the old value, but the connectionState = waiting, so I added the check to see if it's active.

StreamProvider on the other hand keeps providing the old value, probably since there is no check to see if the stream "really" outputs a new value instead of just the previous one while there is no actual new data? The updateShouldNotify doesn't do anything in this case.

To conclude:

  • initial state: both emit same value
  • new state: new workoutId value, StreamBuilder (after checking for an active connectionstate, supplies a new UserWorkout object. StreamProvider still provides the old UserWorkout object. If I remove the check on active connection state, both code blocks behave the same.

Thanks in advance!

All 4 comments

When I add a Provider to my StreamBuilder code block, it also works, but it seems not right? The widget is something on my home screen that doesn't get disposed, so the stream doesn't get detached either.

return StreamBuilder<UserWorkout>(
  stream: UserWorkouts().streamSingle(userId, workoutId),
  builder: (context, snapshot) {
    if (snapshot.connectionState != ConnectionState.active) {
      return Splash();
    }
    UserWorkout userWorkout = snapshot.data;
    if (userWorkout == null) {
      return Splash();
    }
    LogService.log('StreamBuilder<UserWorkout>_${userWorkout.id}');
    return Provider<UserWorkout>(
      create: (_) => userWorkout,
      child: Builder(
        builder: (context) {
          return child;
        },
      ),
    );
  },
);

You can do:

StreamProvider<UserWorkout>.value(
  value: UserWorkouts().streamSingle(userId, workoutId),
  ...
)

@arnoutvandervorst How did you do you it ?
I'm facing the same dilema, I changed my code using StreamProvider for StreamBuilder to access ConnectionState, but I'd like to get the Provider data down the widget tree..

You can do:

StreamProvider<UserWorkout>.value(
  value: UserWorkouts().streamSingle(userId, workoutId),
  ...
)

Trying to implement similar code, if I change value of userId the stream doesn't seem to update 馃憥

@arnoutvandervorst could post the solution here if @rrousselGit suggestion worked thanks

Was this page helpful?
0 / 5 - 0 ratings

Related issues

FaizanKamal7 picture FaizanKamal7  路  6Comments

MaxTenco picture MaxTenco  路  5Comments

dikir picture dikir  路  5Comments

sanekyy picture sanekyy  路  5Comments

usherwalce picture usherwalce  路  5Comments