在这种情况下,如何在 Flutter 中正确实现 FutureBuilder?

How do I correctly implement a FutureBuilder in Flutter in this case?

我正在尝试显示不同图像的水平滚动列表视图。这应该通过 Widget MultipleImageDemo 来实现。我在 loadAssets() 中使用 MultipleImagePicker 创建从 iPhone 图库中选择的图像的资产列表。然后,我将这些资产转换为文件,以便我可以使用来自 的 getImageFileFromAssets(Asset assets) 在 ListView 中显示它们。但是,将资产转换为文件的函数是异步的,因此当我尝试在 Widget build(BuildContext context) 中使用此函数时,我需要使用 FutureBuilder。

这就是我尝试实现它的方式:

Future<File> getImageFileFromAssets(Asset asset) async {
  final byteData = await asset.getByteData();

  final tempFile =
      File("${(await getTemporaryDirectory()).path}/${asset.name}");
  final file = await tempFile.writeAsBytes(
    byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes),
  );

class MultipleImageDemo extends StatefulWidget {
  @override
  _MultipleImageDemoState createState() => _MultipleImageDemoState();
}

class _MultipleImageDemoState extends State<MultipleImageDemo> {
  List<Asset> images = <Asset>[];

  @override
  void initState() {
    super.initState();
  }

  Future<ListView> DisplayPhotos() async {
    List<File> displayedPhotos = <File>[];
    for (var i = 0; i < images.length; i++) {
      File image_file = await getImageFileFromAssets(images[i]);
      displayedPhotos.add(image_file);
    }
    return ListView(
        scrollDirection: Axis.horizontal,
        children: List.generate(displayedPhotos.length, (index) {
          File displayedPhoto = displayedPhotos[index];
          return Container(
              height: MediaQuery.of(context).size.height,
              width: MediaQuery.of(context).size.width,
              child: Image.file(displayedPhoto));
        }));
  }

Future<void> loadAssets() async {
    List<Asset> resultList = <Asset>[];
    String error = 'No Error Detected';

    try {
      resultList = await MultiImagePicker.pickImages(
        maxImages: 300,
        enableCamera: true,
        selectedAssets: images,
        cupertinoOptions: CupertinoOptions(takePhotoIcon: "chat"),
        materialOptions: MaterialOptions(
          actionBarColor: "#abcdef",
          actionBarTitle: "Example App",
          allViewTitle: "All Photos",
          useDetailsView: false,
          selectCircleStrokeColor: "#000000",
        ),
      );
    } on Exception catch (e) {
      error = e.toString();
    }

    if (!mounted) return;

    setState(() {
      images = resultList;
      // _error = error;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        height: MediaQuery.of(context).size.height,
        width: MediaQuery.of(context).size.width,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              child: Text("Pick images"),
              onPressed: loadAssets,
            ),
            Expanded(
                child: FutureBuilder<ListView>(
                    future: DisplayPhotos(),
                    builder: (BuildContext context,
                        AsyncSnapshot<ListView> snapshot) {
                      List<Widget> children;
                      if (snapshot.hasData) {
                        children = <Widget>[
                          const Icon(
                            Icons.check_circle_outline,
                            color: Colors.green,
                            size: 60,
                          ),
                          Padding(
                            padding: const EdgeInsets.only(top: 16),
                            child: Text('Result: ${snapshot.data}'),
                          )
                        ];
                      }
                      return Center(
                        child: Column(
                          mainAxisAlignment: MainAxisAlignment.center,
                          crossAxisAlignment: CrossAxisAlignment.center,
                          children: children,
                        ),
                      );
                    })),
          ],
        ),
      ),
    );
  }
}

这是我得到的错误:

The following assertion was thrown building FutureBuilder<ListView>(dirty, state: _FutureBuilderState<ListView>#66af4):
'package:flutter/src/widgets/framework.dart': Failed assertion: line 1741 pos 14: 'children != null': is not true.
2

Either the assertion indicates an error in the framework itself, or we should provide substantially more information in this error message to help you determine and fix the underlying cause.
In either case, please report this assertion by filing a bug on GitHub:
  https://github.com/flutter/flutter/issues/new?template=2_bug.md
The relevant error-causing widget was
FutureBuilder<ListView>
package:project_startup/screens/addPage.dart:279
When the exception was thrown, this was the stack
#2      new MultiChildRenderObjectWidget
package:flutter/…/widgets/framework.dart:1741
#3      new Flex
package:flutter/…/widgets/basic.dart:4371
#4      new Column
package:flutter/…/widgets/basic.dart:4939
#5      _MultipleImageDemoState.build.<anonymous closure>
package:project_startup/screens/addPage.dart:323
#6      _FutureBuilderState.build
package:flutter/…/widgets/async.dart:775

如何正确实现 FutureBuilder?有必要用吗?

This is what is the simulator shows when I run this app even after I have selected several images from the gallery

编辑

要显示图像,您可以这样做:

return Center(
  child: Column(
    mainAxisAlignment: MainAxisAlignment.center,
    crossAxisAlignment: CrossAxisAlignment.center,
    children: [snapshot.data, ...children], // this line
  ),
);

List<Widget> children; 更改为 List<Widget> children = []; 以便初始化。

问题出在:

return Center(
  child: Column(
    mainAxisAlignment: MainAxisAlignment.center,
    crossAxisAlignment: CrossAxisAlignment.center,
    children: children, // this line
  ),
);

因为加载快照时 children 为空(没有数据),您会在控制台中收到该错误。

snapshot.data插入children然后在返回的容器中显示children似乎已经解决了问题。非常感谢提供帮助的人:)。

Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        height: MediaQuery.of(context).size.height,
        width: MediaQuery.of(context).size.width,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              child: Text(PICKIMAGES),
              onPressed: loadAssets,
            ),
            Expanded(
                child: FutureBuilder<Container>(
                    future: DisplayPhotos(),
                    builder: (BuildContext context,
                        AsyncSnapshot<Container> snapshot) {
                      List<Widget> children = [];
                      if (snapshot.hasData) {
                        children = <Widget>[
                          snapshot.data,
                        ];
                      }
                      return Container(
                          height: MediaQuery.of(context).size.height,
                          width: MediaQuery.of(context).size.width,
                          child: ListView(
                              children: children));
                    })),
          ],
        ),
      ),
    );
  }
}