1

I am currently in the process of learning Flutter through a book and I've stumbled upon an issue I can't solve by myself. This is the very first time I ask something on stackoverflow so I apologise if it's not clear.

I have a video I want to play and when the video is playing I would like to change the play button to show a pause icon and vice versa. Right now I can play/pause the video using a Riverpod provider but I can't seem to update the Icon on my button.

Should I be using a StreamProvider for this case?

the provider:

final VideoPlayerController vpc =
    VideoPlayerController.asset('assets/video.mov');
final videoProvider = Provider<VideoPlayerController>((ref) => vpc
  ..initialize()
  ..setVolume(0)
  ..setLooping(true));

the widget using the provider:

class VideoPage extends ConsumerWidget {
  const VideoPage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return Scaffold(
      appBar: AppBar(
          title: const Text('Video Page'), backgroundColor: Colors.green),
      body: ListView(children: [
        Column(children: [
          AspectRatio(
            aspectRatio: 872 / 1320,
            child: VideoPlayer(ref.watch(videoProvider)),
          )
        ]),
        ElevatedButton(
            onPressed: () => ref.read(videoProvider).value.isPlaying
                ? vpc.pause()
                : vpc.play(),
            child: Icon(ref.read(videoProvider).value.isPlaying
                ? Icons.pause_circle
                : Icons.play_arrow))
      ]),
    );
  }
}

Please let me know what I am doing wrong. I think I shouldn't be calling the vpc variable to play or pause the video? Should I use the .update() method to update the video's state?

Thanks for the help.

wim raes
  • 11
  • 1
  • I don't think you should use riverpod like that. Your VideoPlayerController should be tied to a specific widget not shared through a "global state" using a state management solution. – Guillaume Roux Apr 26 '23 at 16:35

1 Answers1

0

It is rather late but I encountered the same scenario where I couldnt maintain the VideoPlayerController state inside the widget to avoid unnecessary rebuilds of the VideoPlayer widget. In your case, you have to wrap the widgets that are listening to the changes in Consumer() widget and they will rebuild each time the value changes.

class VideoPage extends ConsumerWidget {
  const VideoPage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return Scaffold(
      appBar: AppBar(
          title: const Text('Video Page'), backgroundColor: Colors.green),
      body: ListView(children: [
        Column(children: [
          AspectRatio(
            aspectRatio: 872 / 1320,
            child: VideoPlayer(ref.watch(videoProvider)),
          )
        ]),
        Consumer(
          builder: (context,ref,_) => ElevatedButton(
            onPressed: () => ref.read(videoProvider).value.isPlaying
                ? vpc.pause()
                : vpc.play(),
            child: Icon(ref.read(videoProvider).value.isPlaying
                ? Icons.pause_circle
                : Icons.play_arrow)))
      ]),
    );
  }
}

Also consider creating custom classes to manage state to easily manage logic outside the widgets. StateProvider could be a better solution.

Nengha
  • 36
  • 4