使用Chewie控制器在生成异常期间调用setState()或markNeedsBuild()

时间:2019-12-27 06:03:55

标签: flutter dart

我使用以下代码在屏幕上播放视频。当我点击控制器上的全屏图标时,会得到在构建过程中调用的 setState()或markNeedsBuild()异常。当我点击该图标时,屏幕应该在风景中变为全屏。可以,但随后又恢复为纵向(即设备方向)。

调度VideoPlayerController的通知时引发了以下断言: 在构建期间调用setState()或markNeedsBuild()。 调试控制台显示:

This MaterialControls widget cannot be marked as needing to build because the framework is already in the process of building widgets.  A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was: MaterialControls
dependencies: [_InheritedTheme, _LocalizationsScope-[GlobalKey#8836f], _ChewieControllerProvider]
state: _MaterialControlsState#84529
The widget which was currently being built when the offending call was made was: VideoApp
dirty
state: VideoAppState#8eaa6
When the exception was thrown, this was the stack
Element.markNeedsBuild.<anonymous closure>
Element.markNeedsBuild
State.setState
_MaterialControlsState._updateState
ChangeNotifier.notifyListeners
...
The VideoPlayerController sending notification was: VideoPlayerController#cc7a6(VideoPlayerValue(duration: 0:11:43.069000, size: Size(640.0, 360.0), position: 0:00:03.609000, buffered: [DurationRange(start: 0:00:00.000000, end: 0:00:10.543000)], isPlaying: true, isLooping: false, isBuffering: falsevolume: 1.0, errorDescription: null))

这是我当前正在使用的代码。

import 'package:flutter/material.dart';
import 'package:chewie/chewie.dart';
import 'package:flutter/services.dart';
import 'package:video_player/video_player.dart';

typedef void EndOfVideo();

class VideoApp extends StatefulWidget {

  final VideoAppState _videoAppState = VideoAppState();

  final String videoUrl;
  final EndOfVideo endOfVideo;
  final bool autoPlay;

  VideoApp({
    this.videoUrl,
    this.endOfVideo,
    this.autoPlay
  });

  @override
  State<StatefulWidget> createState() => _videoAppState;

}

class VideoAppState extends State<VideoApp> {

  bool _eovReached = false;

  // bool wasLandscape = false;
  // bool leaveFullscreen = false;

  VideoPlayerController _videoPlayerController;
  ChewieController _chewieController;
  VoidCallback listener;

  VideoAppState() {
    listener = () {
      if(_videoPlayerController.value.initialized) {
        Duration duration = _videoPlayerController.value.duration;
        Duration position = _videoPlayerController.value.position;
        if (duration.inSeconds - position.inSeconds < 3) {
          if(!_eovReached) {
            _eovReached = true;
            widget.endOfVideo();
          }
        }
      }
    };
  }

  initialize(){    
    if(_videoPlayerController != null && _videoPlayerController.value.isPlaying) {
      _videoPlayerController.pause();
    }
    _videoPlayerController = VideoPlayerController.network(
      widget.videoUrl
    ); 
    if(_chewieController != null) {
      _chewieController.dispose();
    }   
    _chewieController = ChewieController(
      allowedScreenSleep: false,
      allowFullScreen: true,
      // uncomment line below to make video fullscreen when play button is hit
      // fullScreenByDefault : true,
      deviceOrientationsAfterFullScreen: [
        DeviceOrientation.portraitUp,
        DeviceOrientation.portraitDown,
        DeviceOrientation.landscapeLeft,
        DeviceOrientation.landscapeRight,   
      ],
      videoPlayerController: _videoPlayerController,
      aspectRatio: 16 / 9,
      autoPlay: false,
      looping: false,
      autoInitialize: false,      
    );  

    _videoPlayerController.addListener(listener);    
    _videoPlayerController.initialize();
  }

  @override
  void initState() {    
    super.initState();  
    try {  
      this.initialize();      
    }catch(e){}
  }

  @override
  void didUpdateWidget(VideoApp oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (this.mounted){
      if(oldWidget.videoUrl != widget.videoUrl) {
        try {  
          this.initialize();
        }catch(e){

        }
      }
    }
  }


  @override
  void dispose() {    
    _videoPlayerController.dispose();
    _chewieController.dispose();
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp,
      DeviceOrientation.portraitDown,
      DeviceOrientation.landscapeRight,
      DeviceOrientation.landscapeLeft,
    ]);
    super.dispose();
  }


  @override
  Widget build(BuildContext context) {     
    if(widget.autoPlay) {
      _videoPlayerController.play();
    }
    return new Container(
      child: new Center(
        child: new Chewie(
          controller: _chewieController,
        )        
      ),
    );    
  }
}

我的问题是什么可能导致此错误,以及如何解决此问题。当设备的方向为横向或横向时,我也想使视频播放器全屏显示。 让我知道是否在这里添加其他内容。 谢谢。

编辑:

我已修复异常。感谢易卜拉欣·卡拉汉(Ibrahim Karahan)!当设备转为横向时,我需要使视频播放器全屏显示的帮助。再次感谢。

0 个答案:

没有答案