如何解决Flutter extended_image:在构建过程中调用 setState() 或 markNeedsBuild() 视频缩略图状态视频小部件
我正在使用包 homebrew 从网络加载图像并在加载或出错时显示闪烁。
当我尝试在 setState() or markNeedsBuild() called during build
中调用 setState 时遇到此错误 loadStateChanged
事实上,我有两个小部件,一个 VideoThumbnail
负责从网络加载缩略图,另一个 VideoDesc
应该显示缩略图说明。
我在 VideoThumbnail
小部件上创建了两个状态变量,它们应该传递给 VideoDesc
小部件
videoLoading = true;
videoError = false;
这是我遵循 repo 示例的代码:
视频缩略图状态
class _VideoThumbnailState extends State<VideoThumbnail>
with SingleTickerProviderStateMixin {
bool videoLoading;
bool videoError;
AnimationController _controller;
@override
void initState() {
videoLoading = true;
videoError = false;
_controller = AnimationController(
vsync: this,duration: const Duration(seconds: 3),);
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
print("Build Process Complete");
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container(
width: widget.width,child: Column(
crossAxisAlignment: CrossAxisAlignment.start,children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.circular(4.0),child: ExtendedImage.network(
widget.videoUrl,width: widget.width,height: (widget.width) * 3 / 4,loadStateChanged: (ExtendedImageState state) {
switch (state.extendedImageLoadState) {
case LoadState.loading:
_controller.reset();
setState(() {
videoError = false;
videoLoading = true;
});
return Shimmer.fromColors(
child: Container(
decoration: Boxdecoration(
borderRadius: BorderRadius.circular(4.0),),baseColor: Colors.black12,highlightColor: Colors.white24,);
break;
case LoadState.completed:
_controller.forward();
setState(() {
videoError = false;
videoLoading = false;
});
return FadeTransition(
opacity: _controller,child: ExtendedRawImage(
image: state.extendedImageInfo?.image,);
break;
case LoadState.Failed:
_controller.reset();
state.imageProvider.evict();
setState(() {
videoError = true;
videoLoading = false;
});
return Container(
width: widget.width,decoration: Boxdecoration(
image: decorationImage(
image: Assetimage("assets/img/not-found.png"),fit: BoxFit.fill,);
break;
default:
return Container();
}
},VideoDesc(
desc: widget.desc,videoError: videoError,videoLoading: videoLoading,)
],);
}
}
视频小部件
class VideoDesc extends StatelessWidget {
final String desc;
final bool videoLoading;
final bool videoError;
const VideoDesc({
Key key,@required this.desc,this.videoLoading = true,this.videoError = false,}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
child: videoError || videoLoading
? Shimmer.fromColors(
baseColor: Colors.grey[700],child: Column(
crossAxisAlignment: CrossAxisAlignment.start,children: <Widget>[
SizedBox(height: 12.0),Container(
width: double.infinity,height: 8.0,decoration: Boxdecoration(
color: Colors.grey[900],borderRadius: BorderRadius.circular(2.0),SizedBox(height: 12.0),Container(
width: 80.0,],)
: Column(
crossAxisAlignment: CrossAxisAlignment.start,children: <Widget>[
SizedBox(height: 12.0),Text(
desc,style: TextStyle(
color: Colors.white,fontSize: 11.0,overflow: TextOverflow.ellipsis,SizedBox(height: 5.0),Text(
"361,143,203 views",style: TextStyle(
color: Colors.white54,fontSize: 12.0,);
}
}
谁能帮我解决这个问题?或者,如果有更好的方法来获取 extendedImageLoadState
值并将其传递给另一个小部件而不调用 loadStateChanged
解决方法
您不能在构建过程中调用 setState
。
如果您确实需要,您可以改为使用:
WidgetsBinding.instance.addPostFrameCallback(() => setState((){}));
但是,请记住,将它放在您的 switch-case
上会安排无限循环的重建,而这也是您不想要的。
我建议您重新构建您的 UI 逻辑或至少使其成为有条件的:
if(!videoLoading) {
WidgetsBinding.instance.addPostFrameCallback(() => setState((){
videoError = false;
videoLoading = true;
}));
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。