繁体   English   中英

Flutter video_player 处置

[英]Flutter video_player dispose

我正在使用带有video_playerprovider来管理 state。

VideoProvider 有:

videoPlayerController = VideoPlayerController.network(...);

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

以前的视频是否正在被 GC 处理? 这有什么性能问题吗? 我想在切换到新视频之前摆脱以前的视频和使用的资源。 我不能在切换之前使用videoPlayerController.dispose() ,因为它会导致错误。

当您调用dispose时,您的 controller 仍在被VideoPlayer小部件使用。 首先,您需要确保不再使用它(将 state 中的 controller 设置为 null)并在调用 dispose 之后。

我不确定你的 state 通过 Provider 管理,但我会给你一个例子,如何使用常规 State 做到这一点。

  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. 创建一个包含VideoPlayerStatefulWidget class 并在init方法中初始化 videoPlayerController。 假设您创建了一个名为 MyVideoPlayer 的 StatefulWidget class 然后在构造函数中接受两个变量,即 i> String videoLink ii> UniqueKey()

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

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();
} ...
  1. 将您正在播放视频的主 dart 文件的VideoPlayer实例替换为您之前创建的 class 即MyVideoPlayer并传递 videoLink 和UniqueKey()

  2. 现在,每当您想更改视频时,只需更新主 dart 文件的setState(() {})内的 videoLink,然后通过完全处理旧的 VideoPlayer 实例创建一个新的 VideoPlayer 实例。

注意 - 这里的主要工作是由 UniqueKey() 完成的,通过传递 UniqueKey() 你说 flutter 来创建这个特定 class 的新唯一实例;

你可以使用它:

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

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

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 ,但您当然可以进行更改。

稍后我们需要使用addListener方法检查video何时finished (我猜)。

感谢此链接中的某人,这解决了我的问题

void dispose() {
        _controller.pause();
        _controller?.dispose();
        //ignore below
        audioPlayer.stop();
        audioPlayer?.dispose();
        super.dispose();
      }

我正在制作 Instagram 网格视图。 每次我选择一个新文件时,我都应该更新我的缩略图。 但是我的有状态小部件无法识别更新。 dispose 方法没有启动。

最后我想到了这个。 希望这会对某人有所帮助。

class _SelectedVideo extends StatefulWidget {
  const _SelectedVideo({
    Key? key,
    required this.file,
  }) : super(key: key);
  final File file;

  @override
  State<_SelectedVideo> createState() => _SelectedVideoState();
}

class _SelectedVideoState extends State<_SelectedVideo> {
  VideoPlayerController? _controller;

  void _initVideoPlayer(File file) async {
    _controller = VideoPlayerController.file(
      file,
    );
    await _controller!.initialize();
    _controller!.setVolume(0);
    _controller!.play();

    setState(() {});
  }

  @override
  void initState() {
    super.initState();
    _initVideoPlayer(widget.file);
  }

  @override
  void didUpdateWidget(covariant _SelectedVideo oldWidget) {
    // I'm disposing controller all the time when widget updates
    _controller?.dispose();

    _initVideoPlayer(widget.file);
    super.didUpdateWidget(oldWidget);
  }

  @override
  void dispose() {
    _controller?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    if (_controller == null) return Container();
    return Container(
      color: Colors.black,
      height: 375,
      width: double.infinity,
      child: FittedBox(
        fit: BoxFit.cover,
        clipBehavior: Clip.hardEdge,
        child: SizedBox(
          width: _controller!.value.size.width,
          height: _controller!.value.size.height,
          child: AspectRatio(
            aspectRatio: _controller!.value.aspectRatio,
            child: VideoPlayer(_controller!),
          ),
        ),
      ),
    );
  }
}

暂无
暂无

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

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