此ValueListenableBuilder小部件不能标记为需要构建

时间:2020-05-02 03:19:29

标签: flutter

在我的应用程序的简单部分中,我将此值定义为ValueNotifier

final ValueNotifier<List<MediaDropDownStructure>> _mediaFoldersList = ValueNotifier<List<MediaDropDownStructure>>([]);

我在DropDownBottom项中使用了此变量来填充它们并创建菜单,然后在StreamBuilder内的此代码中填充了该变量:

StreamBuilder<List<MediaModel>>(
    stream: _globalBloc.storageMediaBloc.imagesMedia$,
    builder: (context, snapshot) {
      if (!snapshot.hasData) {
        return const Center(
          child: CircularProgressIndicator( ),
        );
      }
      final List<MediaModel> _allImages = snapshot.data;
      _mediaFoldersList.value = _allImages.map( (image) => MediaDropDownStructure( image.folder, image.folder ) ).toList();

      final MediaModel _all = _allImages[0];
      return GridView.builder(

      ...

我在DropDownBotton中使用它,就像这样:

child: ValueListenableBuilder(
  valueListenable: _mediaFoldersList,
    builder: (context, List<MediaDropDownStructure> items,child)=>DropdownButtonHideUnderline(
      child: DropdownButton<MediaDropDownStructure>(
        value: _chooseFolderName.value,
        hint: Text("please choose",style: AppTheme.of(context).caption(),),
        items: items.map((MediaDropDownStructure menuItem) {
          return DropdownMenuItem<MediaDropDownStructure>(
            value: menuItem,
            child: Text(menuItem.folderPath),
          );
        }).toList(),
        onChanged: (_) {},
      ),
    ),
),

我得到这个错误:

The following assertion was thrown while dispatching notifications for ValueNotifier<List<MediaDropDownStructure>>:
setState() or markNeedsBuild() called during build.

This ValueListenableBuilder<List<MediaDropDownStructure>> 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: ValueListenableBuilder<List<MediaDropDownStructure>>
  dependencies: [_InheritedTheme, _LocalizationsScope-[GlobalKey#2b62a]]
  state: _ValueListenableBuilderState<List<MediaDropDownStructure>>#6c134
The widget which was currently being built when the offending call was made was: StreamBuilder<List<MediaModel>>
  dirty
  state: _StreamBuilderBaseState<List<MediaModel>, AsyncSnapshot<List<MediaModel>>>#cbf2d

1 个答案:

答案 0 :(得分:1)

问题在于,在streambuilder建立其状态的同时_mediaFoldersList的值也发生了变化,因此它还将开始构建ValueListenableBuilder,并且由于两个构建器无法一起构建而正在制造问题。

要解决此问题,您可以在1微秒后更改_mediaFoldersList的值,以便streambuilder builder完成其构建方法,然后ValueListenableBuilder可以构建。

类似下面的制作方法。

 changevaluenotifiervalue(_allImages) async {

    await Future.delayed(Duration(microseconds: 1));
  _mediaFoldersList.value = _allImages.map( (image) => MediaDropDownStructure( image.folder, image.folder ) ).toList();

  }

在更改其值的地方调用此方法。

final List<MediaModel> _allImages = snapshot.data;
      //_mediaFoldersList.value = _allImages.map( (image) => MediaDropDownStructure( image.folder, image.folder ) ).toList();  //commented 
  changevaluenotifiervalue(_allImages);  // added
  final MediaModel _all = _allImages[0];