简体   繁体   English

Flutter Riverpod:使用 StreamProvider 返回 2 stream

[英]Flutter Riverpod : return 2 stream with StreamProvider

I have music player application using package Asset Audio Player and Flutter Riverpod as State Management.我有使用 package资产音频播放器Flutter Riverpod作为 State 管理的音乐播放器应用程序。 I want listen 2 things stream:我想听两件事 stream:

  1. Listen current duration of song收听歌曲的当前时长
  2. Listen current song played收听当前播放的歌曲
final currentSongPosition = StreamProvider.autoDispose<Map<String, dynamic>>((ref) async* {
  final AssetsAudioPlayer player = ref.watch(globalAudioPlayers).state;
  ref.onDispose(() => player.dispose());

  final Stream<double> _first = player.currentPosition.map((event) => event.inSeconds.toDouble());
  final Stream<double> _second =
      player.current.map((event) => event?.audio.duration.inSeconds.toDouble() ?? 0.0);

  final maps = {};
  maps['currentDuration'] = _first;
  maps['maxDurationSong'] = _second;
  return maps; << Error The return type 'Map<dynamic, dynamic>' isn't a 'Stream<Map<String, dynamic>>', as required by the closure's context.
});

How can i return 2 stream into 1 StreamProvider then i can simply using like this:我怎样才能将 2 stream 返回到 1 StreamProvider然后我可以像这样简单地使用:

Consumer(
              builder: (_, watch, __) {
               
                final _currentSong = watch(currentSongPosition);

                return _currentSong.when(
                  data: (value) {
                    final _currentDuration = value['currentDuration'] as double;
                    final _maxDuration = value['maxDuration'] as double;
                    return Text('Current : $_currentDuration, Max :$_maxDuration');
                  },
                  loading: () => Center(child: CircularProgressIndicator()),
                  error: (error, stackTrace) => Text('Error When Playing Song'),
                );
               
              },
            ),

I would start by creating a StreamProvider for each Stream :我将从为每个Stream创建一个StreamProvider开始:

final currentDuration = StreamProvider.autoDispose<double>((ref) {
  final player = ref.watch(globalAudioPlayers).state;
  return player.currentPosition.map((event) => event.inSeconds.toDouble());
});

final maxDuration = StreamProvider.autoDispose<double>((ref) {
  final player = ref.watch(globalAudioPlayers).state;
  return player.current.map((event) => event?.audio.duration.inSeconds.toDouble() ?? 0.0);
});

Next, create a FutureProvider to read the last value of each Stream .接下来,创建一个FutureProvider来读取每个Stream的最后一个值。

final durationInfo = FutureProvider.autoDispose<Map<String, double>>((ref) async {
  final current = await ref.watch(currentDuration.last);
  final max = await ref.watch(maxDuration.last);
  return {
    'currentDuration': current,
    'maxDurationSong': max,
  };
});

Finally, create a StreamProvider that converts durationInfo into a Stream .最后,创建一个StreamProviderdurationInfo转换为Stream

final currentSongPosition = StreamProvider.autoDispose<Map<String, double>>((ref) {
  final info = ref.watch(durationInfo.future);
  return info.asStream();
});

This answer is another approach what @AlexHartford do.这个答案是@AlexHartford 所做的另一种方法。

Current solution for my case is using package rxdart CombineLatestStream.list() , this code should be look then:我的案例的当前解决方案是使用 package rxdart CombineLatestStream.list() ,然后应该查看此代码:

StreamProvider流提供者

final currentSongPosition = StreamProvider.autoDispose((ref) {
  final AssetsAudioPlayer player = ref.watch(globalAudioPlayers).state;

  final Stream<double> _first = player.currentPosition.map((event) => event.inSeconds.toDouble());
  final Stream<double> _second =
      player.current.map((event) => event?.audio.duration.inSeconds.toDouble() ?? 0.0);

  final tempList = [_first, _second];
  return CombineLatestStream.list(tempList);
});

How to use it:如何使用它:

Consumer(
              builder: (_, watch, __) {
                final players = watch(globalAudioPlayers).state;
                final _currentSong = watch(currentSongPosition);
                return _currentSong.when(
                  data: (value) {
                    final _currentDuration = value[0];
                    final _maxDuration = value[1];
                    return Slider.adaptive(
                      value: _currentDuration,
                      max: _maxDuration,
                      onChanged: (value) async {
                        final newDuration = Duration(seconds: value.toInt());
                        await players.seek(newDuration);
                        context.read(currentSongProvider).setDuration(newDuration);
                      },
                    );
                  },
                  loading: () => const Center(child: CircularProgressIndicator()),
                  error: (error, stackTrace) => Text(error.toString()),
                );
              },
            ),

But this approach have drawback, the code is hard to readable.但是这种方法有缺点,代码难以阅读。 Especially when use in Consumer , I have to know the order of return result.特别是在Consumer中使用时,我必须知道返回结果的顺序。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在 Flutter 中使用 Riverpod 关闭 StreamProvider - How to close StreamProvider with Riverpod in Flutter 将参数传递给 Flutter Riverpod StreamProvider - Pass parameters to Flutter Riverpod StreamProvider 将地理定位器 GPS stream 与 Riverpod StreamProvider 一起使用 - Using geolocator GPS stream with Riverpod StreamProvider 如何在 Flutter 中更改 StreamProvider 中的 stream - How to change the stream in StreamProvider in Flutter 使用 Flutter Riverpod 的 StreamProvider 从 Firestore 获取特定文档 - Using Flutter Riverpod's StreamProvider to fetch a specific document from Firestore Flutter Riverpod StreamProvider 在构建 Widget 之前不等待循环完成 - Flutter Riverpod StreamProvider not waiting for for loop to finish before building Widget 在 Flutter - Dart 之外使用 StreamProvider 的 RiverPod 方式是什么? - What is the RiverPod way to Consume a StreamProvider outside of Flutter - Dart only Riverpod 的 StreamProvider 只产生一次 StreamValue | Flutter &amp; Hive - Riverpod's StreamProvider yields StreamValue only once | Flutter & Hive 为什么当数据库为 null 时,即使 Stream.empty() 应该返回,RiverPod StreamProvider 仍会卡在加载中 - Why is RiverPod StreamProvider stuck in loading even though Stream.empty() should be returning when database is null Riverpod 的 StreamProvider 在读取 Hive 的盒子时卡在加载中 | Flutter - Riverpod's StreamProvider stuck in loading when reading Hive's box | Flutter
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM