颤抖的video_player处置

时间:2019-11-20 13:45:07

标签: flutter dart

我正在将providervideo_player一起使用来管理状态。

VideoProvider具有:

videoPlayerController = VideoPlayerController.network(...);

当用户切换到新视频(同一屏幕)时,我经常更改。如果我直接将新的VideoPlayerController.network(...)分配给videoPlayerController,则旧视频仍会播放,您可以听到声音。解决方法是先videoPlayerController.pause(),然后再分配新的VideoPlayerCOntroller.network

上一个视频是否已由GC处理?这有任何性能问题吗?我想摆脱以前的视频和切换到新视频之前使用的资源。切换之前,我无法videoPlayerController.dispose(),因为它会导致错误。

4 个答案:

答案 0 :(得分:2)

调用dispose时, VideoPlayer 小部件仍在使用您的控制器。首先,您需要确保不再使用它(将状态为controller的控制器设置为null),然后再调用dispose。

我不确定您是如何通过提供商进行状态管理的,但我将举例说明如何使用常规状态。

  VideoPlayerController _controller;

  void _initController(String link) {
    _controller = VideoPlayerController.network(link)
      ..initialize().then((_) {
        setState(() {});
      });
  }

  Future<void> _onControllerChange(String link) async {
    if (_controller == null) {
      // If there was no controller, just create a new one
      _initController(link);
    } else {
      // If there was a controller, we need to dispose of the old one first
      final oldController = _controller;

      // Registering a callback for the end of next frame
      // to dispose of an old controller
      // (which won't be used anymore after calling setState)
      WidgetsBinding.instance.addPostFrameCallback((_) async {
        await oldController.dispose();

        // Initing new controller
        _initController(link);
      });

      // Making sure that controller is not used by setting it to null
      setState(() {
        _controller = null;
      });
    }
  }

答案 1 :(得分:0)

我知道是以后,但是我想我找到了一种解决此问题的方法。

1。创建initPlayer()(我是使用Provider创建的)

  void initPlayer( {pause = false, update = false, updateUrl = ""} ) async {
  var isPlaying = false;

  if (controller == null) {
    controller = VideoPlayerController.file(File(url))..addListener(() {
    isPlaying = true;
    notifyListeners();
   })..initialize().then((value) => notifyListeners());
   controller.play();
   } else {
     print ("Controller is playing...");
   if (pause) {
    if (controller.value.isPlaying) {
      controller.pause();
    } else {
      controller.play();
    }
   }
   if (update && updateUrl != "") {
    final oldController = controller;
    await oldController.dispose();
    controller = VideoPlayerController.file(File(updateUrl))..addListener(() {
      isPlaying = true;
      notifyListeners();
       })..initialize().then((value) => notifyListeners());
      controller.play();
    }
  }
}
  1. 在窗口小部件中添加Actionsstartpause change)。

          child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
        FlatButton(
          child: Text("Play Video"),
          color: Colors.red,
          onPressed: () {
            musicPlayerProvider.initPlayer();
          },
        ),
        FlatButton(
          child: Text("Stop Video"),
          color: Colors.pink,
          onPressed: () {
            musicPlayerProvider.initPlayer(pause: true);
          },
        ),
        FlatButton(
          child: Text("Change Video"),
          color: Colors.yellow,
          onPressed: () {
            musicPlayerProvider.initPlayer(update: true,updateUrl: 
                "url");
          },
        ),
      ],),
    

暂时works,但是您当然可以进行更改。

稍后我们需要使用video方法检查finished是否具有addListener。(我猜是)。

答案 2 :(得分:0)

我知道它来晚了,但这会帮助其他有相同问题的人。

我遇到了同样的问题,当用户从列表中选择新视频时,我想更改视频,在进行了如此多的研究之后,我终于自己创建了一个解决方案。

按照以下步骤操作,您可以在同一屏幕的视频播放器中录制视频

  1. 创建一个包含StatefulWidget的{​​{1}}类,并使用VideoPlayer方法初始化videoPlayerController。 假设您创建了一个名为MyVideoPlayer的StatefulWidget类,然后在构造函数中接受两个变量,即 i>字符串videoLink ii> UniqueKey()

注意-您必须将UniqueKey()传递给此类的上级,例如

init
  1. 使用先前创建的类class MyVideoPlayer extends StatefulWidget { final String videoLink; final UniqueKey newKey; MyVideoPlayer(this.videoLink, this.newKey): super(key: newKey); // passing Unique key to dispose old class instance and create new with new data @override _MyVideoPlayerState createState() => _MyVideoPlayerState(); } ... 替换要在其中播放视频的主dart文件的VideoPlayer实例,并传递videoLink和MyVideoPlayer

    < / li>
  2. 现在,只要您想更改视频,只需在主dart文件的UniqueKey()中更新videoLink,然后通过完全丢弃旧视频实例来创建一个新的VideoPlayer实例。

注意-这里的主要工作是由UniqueKey()完成的,通过传递UniqueKey(),您可以说是颤抖地创建了该特定类的新的唯一实例;

答案 3 :(得分:0)

您可以使用它:

@override
  void dispose() {
    if (_controller.value.isPlaying) _controller.pause();
    _controller.removeListener(_videoListener);
    _controller = null;
    super.dispose();
  }