简体   繁体   中英

Identical StreamBuilders in flutter, one is working other returns null

I have two identical stream builders in two different widgets. One works, while the other is receiving no data. This is the widget tree.

在此处输入图像描述

Here is the StreamBuilder

StreamBuilder<AudioPlayerState>(
    stream: _playbackProvider.playbackState,
    builder: (context, snapshot) {
      IconData _playbackButton = Icons.play_circle_filled;

         if (snapshot.hasData) {
             if (snapshot.data == AudioPlayerState.PLAYING) {
                  _playbackButton = Icons.pause_circle_filled;
             } else {
                  _playbackButton = Icons.play_circle_filled;
             }
         }

        return OutlineButton(
             onPressed: () {
               _playButtonClicked(snapshot.data);
             },
             child: Icon(_playbackButton),
             shape: CircleBorder(),
        );
}),

Here is the stream they are both listening to:

Stream<AudioPlayerState> get playbackState {
    return _audioPlayer.onPlayerStateChanged; // using onPlayerStateChanged stream provided by audioplayers plugin.
}

This stream can be accessed by the change notifier provider, in both of these widgets (Scaffolds). The audioplayer is enclosed in a ChangeNotifier class.

class PlaybackProvider with ChangeNotifier {
  String _path;
  AudioPlayer _audioPlayer;

  PlaybackProvider() {
    _audioPlayer = AudioPlayer();
    _audioPlayer.setReleaseMode(ReleaseMode.STOP);
    _audioPlayer.notificationState = AudioPlayerState.STOPPED;
  }

  Stream<Duration> get playbackPosition { // this stream is also working fine in the first screen (widget)
    return _audioPlayer.onAudioPositionChanged;
  }

  Stream<AudioPlayerState> get playbackState {
    return _audioPlayer.onPlayerStateChanged;
  }

//other methods
}

The change notifier is then provided to each of these widgets.

final _playbackProvider = Provider.of<PlaybackProvider>(context);

And the main function,

void main() {
  runApp(MultiProvider(providers: [
    ChangeNotifierProvider(create: (_) => PlaylistProvider()),
    ChangeNotifierProvider(create: (_) => PlaybackProvider()),
  ], child: MyApp()));
}
Stream<Duration> get playbackPosition { // this stream is also working fine in the first screen (widget)
    return _audioPlayer.onAudioPositionChanged;
  }

Are you sure _audioPlayer.onAudioPositionChanged is a BroadcastStream or that it returns the same instance of Strem, It could be the case that the getter is returning different instances each time you call it, one way to be sure you have the same value is to create a StreamProvider and then consume it down in the tree

void main() {
  runApp(MultiProvider(providers: [
    ChangeNotifierProvider(create: (_) => PlaylistProvider()),
    ChangeNotifierProvider(create: (_) => PlaybackProvider()),
    StreamProvider<AudioPlayerState>(create: (context) => Provider.of<PlaybackProvider>(context, listen: false).playbackState)
  ], child: MyApp()));
}

And then instead of StreamBuilder in each widget just use the consumer

return OutlineButton(
  onPressed: () => _playButtonClicked(snapshot.data),
  child: Consumer<AudioPlayerState>(
    builder: (context, data, _) {
      if(data  == AudioPlayerState.PLAYING) return Icon(Icons.pause_circle_filled);
      return Icon(Icons.play_circle_filled);
    }
  ),
  shape: CircleBorder(),
);

Your code and logic is not wrong, but if you're using provider maybe it's better to use all the kind of Providers it provides (unironically) to your advantage. If you want to keep with the StreamBuilder, that's fine too, but without seeing your code of AudioPlayer class it's hard to se what is returning _audioPlayer.onAudioPositionChanged , if it's a simple stream, are you creating it anew in that method, its Broadcast (using the asBroadCast method), etc?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM