简体   繁体   English

如何将函数从子类传递到父类,我收到此错误:在构建期间调用了 setState() 或 markNeedsBuild()

[英]How to pass function from a child class to parent class, I am getting this error: setState() or markNeedsBuild() called during build

Here data(_data =video/ images links, _id= v or i) is coming from an api.这里的 data(_data =video/ images links, _id= v or i) 来自 api。 Here, i made a slideshow of videos and images with a fade in fade out effect, images have a certain time period to display but videos have different lengths so I want to stop the animation till the video has ended, using timer doesn't work as the loading time takes longer and video changes before ending.在这里,我制作了一个带有淡入淡出效果的视频和图像幻灯片,图像有一定的显示时间但视频有不同的长度所以我想停止动画直到视频结束,使用计时器不起作用因为加载时间需要更长的时间,并且视频在结束前会发生变化。 Here I tried to send a callback from a child to parent but I am getting this error.在这里,我试图从孩子向父母发送回调,但我收到了这个错误。

class LogoApp extends StatefulWidget {

  LogoApp(this.data, this.id, this.seconds, this.length);

  final int length;
  final List<String> id;
  final List<String> data;
  final List<int> seconds;
  _LogoAppState createState() => _LogoAppState(data, id, seconds, length);
}

class _LogoAppState extends State<LogoApp> with TickerProviderStateMixin {
  _LogoAppState(this._data, this._id, this._seconds, this._length);

  static int i = 0;
  int _length;
  List<String> _id;
  List<String> _data;
  List<int> _seconds;
  AnimationController controller;
  Animation<double> animation;
  Timer timer;
  Future<dynamic> cachedData;
  List<Map<String, dynamic>> listOfCache = [];
  bool state = false;
  File compressedImage;
  bool videoEnded = false;

  _updateVideoState(bool state) {
    setState(() {
      videoEnded = state;
    });
  }

  int miliSec(int sec) {
    if (sec == 0)
      return 10000;
    else
      return sec * 1000;
  }

  initState() {
    super.initState();
    this.cache(0);
  }

  Future<dynamic> downloadFile(String url) async {
    var fetchedFile = await DefaultCacheManager().getSingleFile(url);
    return fetchedFile;
  }

   void cache(int index) async {
    if (index == _data.length) {
      animate();
      setState(() {
        state = true;
      });

      return;
    }
    var cachedData = await DefaultCacheManager().getSingleFile(_data[index]);
    if (_id[index] == 'i') {
      compressedImage = await FlutterNativeImage.compressImage(
        cachedData.path,
        quality: 75,
        percentage: 100,
      );
      cachedData = compressedImage;
    }

    listOfCache.add({"data": cachedData, "type": _id[index]});
    this.cache(index + 1);
  }

  void animate() {
    controller = AnimationController(
        duration: Duration(milliseconds: 1000), vsync: this);
    animation = CurvedAnimation(parent: controller, curve: Curves.ease);

    animation.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        if (_id[i] == "v") {
          while (true) {
            if (videoEnded) {
              break;
            }
          }
        } else {
          timer = Timer(
            Duration(milliseconds: 10000),
            () {
              controller.reverse();
            },
          );
        }
      } else if (status == AnimationStatus.dismissed) {
        setState(() {
          i++;
          if (i == _length) {
            i = 0;
          }
        });
        controller.forward();
      }
    });
    controller.forward();
  }

  Widget initVideo() {
    return ChewieListItem(
      parentAction: _updateVideoState,
      videoPlayerController: VideoPlayerController.file(listOfCache[i]["data"]),
    );
  }

  Widget build(BuildContext context) {
    if (state == true) {
      return Container(
        height: MediaQuery.of(context).size.height,
        width: MediaQuery.of(context).size.width,
        alignment: Alignment.bottomCenter,
        color: Colors.black,
        child: FadeTransition(
          opacity: animation,
          child: (listOfCache[i]["type"] == "i")
              ? Image.file(
                  listOfCache[i]["data"],
                  fit: BoxFit.fill,
                )
              : initVideo(),
        ),
      );
    } else {
      return Center(child: CircularProgressIndicator());
    }
  }

  @override
  void dispose() {
    super.dispose();
    controller.dispose();
  }
}

class ChewieListItem extends StatefulWidget {
  final ValueChanged<bool> parentAction;
  final VideoPlayerController videoPlayerController;

  ChewieListItem({
    @required this.parentAction,
    this.videoPlayerController,
    Key key,
  }) : super(key: key);

  @override
  _ChewieListItemState createState() => _ChewieListItemState();
}

class _ChewieListItemState extends State<ChewieListItem> {
  ChewieController _chewieController;

  @override
  void initState() {
    super.initState();
    widget.videoPlayerController.addListener(checkVideo);
    _chewieController = ChewieController(
      videoPlayerController: widget.videoPlayerController,
      autoInitialize: true,
      autoPlay: true,
      //looping: true,
      showControls: false,
      errorBuilder: (context, errorMessage) {
        return Center(
          child: Text(
            errorMessage,
            style: TextStyle(color: Colors.white),
          ),
        );
      },
    );
  }

  void checkVideo() {
    if (widget.videoPlayerController.value.position ==
        widget.videoPlayerController.value.duration) {
      widget.parentAction(true);
    } else
      widget.parentAction(false);
  }

  @override
  Widget build(BuildContext context) {
    return Chewie(
      controller: _chewieController,
    );
  }

  @override
  void dispose() {
    super.dispose();
    _chewieController.dispose();
  }
}

Error:错误:

Launching lib\main.dart on D6633 in debug mode...
Built build\app\outputs\apk\debug\app-debug.apk.

�[38;5;248m════════ Exception caught by foundation library ════════════════════════════════�[39;49m
�[38;5;244mThe following assertion was thrown while dispatching notifications for VideoPlayerController:�[39;49m
setState() or markNeedsBuild() called during build.

�[38;5;244mThis LogoApp 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.�[39;49m
�[38;5;244mThe widget on which setState() or markNeedsBuild() was called was: LogoApp�[39;49m
    �[38;5;244mdependencies: [MediaQuery]�[39;49m
    �[38;5;244mstate: _LogoAppState#68420(tickers: tracking 1 ticker)�[39;49m
�[38;5;244mThe widget which was currently being built when the offending call was made was: Container�[39;49m
    �[38;5;244mbottomCenter�[39;49m
    �[38;5;244mbg: BoxDecoration(color: Color(0xff000000))�[39;49m
    �[38;5;244mconstraints: BoxConstraints(w=592.0, h=360.0)�[39;49m
�[38;5;244mWhen the exception was thrown, this was the stack�[39;49m
�[38;5;244m#0      Element.markNeedsBuild.<anonymous closure>�[39;49m
�[38;5;244m#1      Element.markNeedsBuild�[39;49m
�[38;5;244m#2      State.setState�[39;49m
�[38;5;248m#3      _LogoAppState._updateVideoState�[39;49m
�[38;5;248m#4      _ChewieListItemState.checkVideo�[39;49m
�[38;5;244m...�[39;49m
�[38;5;244mThe VideoPlayerController sending notification was: VideoPlayerController#09533(VideoPlayerValue(duration: null, size: null, position: 0:00:00.000000, buffered: [], isPlaying: false, isLooping: false, isBuffering: falsevolume: 1.0, errorDescription: null))�[39;49m
�[38;5;248m════════════════════════════════════════════════════════════════════════════════�[39;49m
I/ExoPlayerImpl( 1537): Init ee97f31 [ExoPlayerLib/2.9.6] [D6633, D6633, Sony, 23]
W/VideoCapabilities( 1537): Unrecognized profile 2130706433 for video/avc
W/AudioCapabilities( 1537): Unsupported mime audio/alac
W/AudioCapabilities( 1537): Unsupported mime audio/dsd
W/VideoCapabilities( 1537): Unsupported mime video/divx
W/VideoCapabilities( 1537): Unsupported mime video/divx311
W/VideoCapabilities( 1537): Unsupported mime video/divx4
W/VideoCapabilities( 1537): Unsupported mime video/mp4v-esdp
I/VideoCapabilities( 1537): Unsupported profile 4 for video/mp4v-es
I/OMXClient( 1537): Using client-side OMX mux.
I/MediaCodec( 1537): [OMX.qcom.video.decoder.avc] setting surface generation to 1573889
D/MediaOutputController( 1537): attach(0x0, 0x9e443180, 0xb5ce7701)
D/MediaCodec( 1537): MediaCodec callback for event 0
D/MediaCodec( 1537): onMediaOutputControllEvent(VIDEO_FLAGS_SET, 0x8ec4755c, 4)
D/MediaCodec( 1537): mVideoOutputFlags = 0x00000000
D/MediaOutputController( 1537): onConnect(): 0x00010003
D/MediaOutputController( 1537): setAudioDevicesState(0x00010003, 1)
D/MediaOutputPolicy( 1537): notifyAudioStateIfNeeded(0x00010003)
D/MediaOutputController( 1537): Registered as audio policy client
I/ExtendedACodec( 1537): setupVideoDecoder()
I/ExtendedACodec( 1537): vpp-enable search is 0 and value is 0
I/ExtendedACodec( 1537): Decoder will be in frame by frame mode
D/ACodec  ( 1537): Found video-output-protection flags set to 00000000
D/SurfaceUtils( 1537): set up nativeWindow 0x980b4a08 for 1280x720, color 0x7fa30c04, rotation 0, usage 0x42002900
I/OMXClient( 1537): Using client-side OMX mux.
D/SurfaceUtils( 1537): set up nativeWindow 0x980b4a08 for 1280x720, color 0x7fa30c04, rotation 0, usage 0x42002900
E/OMXMaster( 1537): A component of name 'OMX.qcom.audio.decoder.aac' already exists, ignoring this one.
D/MediaOutputController( 1537): attach(0x0, 0x9e4432c0, 0xb5ce7701)
D/MediaCodec( 1537): MediaCodec callback for event 0
D/MediaCodec( 1537): onMediaOutputControllEvent(VIDEO_FLAGS_SET, 0x895e355c, 4)
D/MediaCodec( 1537): mVideoOutputFlags = 0x00000000
D/MediaOutputPolicy( 1537): notifyAudioStateIfNeeded(0x00010003)
E/OMXNodeInstance( 1537): setConfig(1:google.aac.decoder, ConfigPriority(0x6f800002)) ERROR: Undefined(0x80001001)
I/ACodec  ( 1537): codec does not support config priority (err -2147483648)
E/OMXNodeInstance( 1537): setConfig(1:google.aac.decoder, ConfigPriority(0x6f800002)) ERROR: Undefined(0x80001001)
I/ACodec  ( 1537): codec does not support config priority (err -2147483648)
I/SoftAAC2( 1537): Reconfiguring decoder: 0->44100 Hz, 0->2 channels
W/ExtendedACodec( 1537): Failed to get Profile and Level from Component
W/ExtendedACodec( 1537): Failed to get Entropy from Component

It Helps me它帮助到我

if(mounted) {
  setState(() {
      videoEnded = state;
  });
} 

暂无
暂无

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

相关问题 (在构建过程中出现错误)在构建过程中调用了 setState() 或 markNeedsBuild()。相关的导致错误的小部件是 MaterialApp - (Getting the error while building) setState() or markNeedsBuild() called during build.The relevant error-causing widget was MaterialApp 在构建 TextField 期间调用 setState() 或 markNeedsBuild() - setState() or markNeedsBuild() called during build TextField flutter 应用程序中的“setState() 或 MarkNeedsBuild() 调用期间”错误 - “setState() or MarkNeedsBuild() called during” error in flutter app 无限滚动列表视图 - 在构建期间调用的setState()或markNeedsBuild - Infinite Scroll listview - setState() or markNeedsBuild called during build 从父类的子类调用函数? - call function from child class in parent class? 如何从父类调用子方法? - How do I call a child's method from the parent class? Flutter:当小部件树被锁定时调用 setState() 或 markNeedsBuild() ... 在方向更改期间 - Flutter: setState() or markNeedsBuild() called when widget tree was locked... during orientation change 我收到“错误放大类片段”吗? - I am getting “Error inflating class fragment”? Android Retrofit:每次我遇到 onFailure 并且我想从子类中获得“title” - Android Retrofit: Every time I am getting onFailure and I want get “title” from child class OnActivityResult 未在 Fragment 中调用,其中意图从适配器类传递 - OnActivityResult not getting called in Fragment where intent pass from adapter class
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM