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



这里 data(_data =video/images links, _id= v or i( 来自 api。在这里,我制作了具有淡入淡出效果的视频和图像的幻灯片,图像有一定的时间段要显示,但视频的长度不同,所以我想停止动画直到视频结束,使用计时器不起作用,因为加载时间更长并且视频在结束之前会发生变化。在这里,我尝试将子项的回调发送到父级,但收到此错误。

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();
}
}

错误:

Launching libmain.dart on D6633 in debug mode...
Built buildappoutputsapkdebugapp-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

它对我有帮助

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

最新更新