在 Flutter 中,如何确保用于构建 GridView 的数据可用?

Posted

技术标签:

【中文标题】在 Flutter 中,如何确保用于构建 GridView 的数据可用?【英文标题】:In Flutter, How can I make sure that the data used to build a GridView is available? 【发布时间】:2021-05-01 22:16:02 【问题描述】:

我有一组文件存储在 App 目录中。每一个都包含要在 GridView Widget 中显示的 Uint8List 数据。由于 Dart 的异步特性,我如何确保在 Widget 构建开始之前可以获取文件的数量和可用的文件名。由于文件/名称的数量是动态的,我必须扫描 App 目录。以下是部分代码sn-p。我把获取文件名和生成 Uint8List 数据集的功能放在 initState 中,但有时不能正常工作。感谢您对此问题的任何反馈。

class _PageAState extends State<PageA> 

    List<String> fileNames=[];
    List<Uint8List> uIntData
    int numFiles=0;
    
    /*get file names (starting with "XYZ", stored in App directory*/
    
    _getFileName() async 
    fileNames = [];
    
    String keyWord = "XYZ";
    
    List files = new List();
 //   var lock = new Lock();   // try https://pub.dev/packages/synchronized package with no luck
   // await lock.synchronized(() async 
      String directory = (await getApplicationDocumentsDirectory()).path;
      files = Directory("$directory").listSync();
      for (FileSystemEntity f in files) 
        if (f.path.contains(keyWord)) 
          fileNames.add(f.path);
          print(f.path);
        
      
    // );
  

  /*get a set of Uint8List data */
  
  _getImageData() async 
    await _getFileName();
    numFiles = fileNames.length;
   
    for (int i = 0; i < numFiles; i++) 
      Uint8List dData =
          (await rootBundle.load(fileNames[i])).buffer.asUint8List();
      uIntData.add(dData);
    
  


 @override
  initState() 
    super.initState();
    /** load Uint8List data set async ***/
    _getImageData();
   

 Widget buildGridView(BuildContext context) 
    var orientation = Orientation.portrait;
    return (GridView.builder(
      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: (orientation == Orientation.portrait) ? 2 : 3),
    // how to make sure that numFiles is properly set ???     
      itemCount: numFiles,
      itemBuilder: (BuildContext ctx, int index) 
        return Padding(
          padding: EdgeInsets.all(20),
          child: Stack(children: <Widget>[
            GestureDetector(
              child: Card(
                shape: Border.all(
                  width: 5,
                ),
                elevation: 20,
                color: Colors.greenAccent,
                child: SizedBox(
                  child: (uIntData.isEmpty || uIntData[index] == null)
                      ? CircularProgressIndicator()
                      : Image.memory(uIntData[index]),
                  width: 120,
                  height: 120,
                ),
              ),
              onTap: () 
              ,
              onLongPress: () 
              ,
            ),
          ]),
        );
      ,
    ));
  
  
    
  @override
  Widget build(BuildContext context) 
    return Scaffold(
      body: buildGridView(context),
    );
   

【问题讨论】:

【参考方案1】:

您必须初始化 uIntDataitemCount 使用您的 uIntData 列表的长度,例如:

声明:

  List<Uint8List> uIntData = [];

清点实物:

  itemCount: uIntData.length,

此外,您可以只用一种方法重构 _getFileName_getImageData,因为当您只能使用一个时,您使用 2 作为 bucle。

【讨论】:

【参考方案2】:

在检索到所有文件后再次尝试刷新 UI:

  @override
  initState() 
    super.initState();
    /** load Uint8List data set async ***/
    _getImageData().then(()
setState(() );
);
 

【讨论】:

以上是关于在 Flutter 中,如何确保用于构建 GridView 的数据可用?的主要内容,如果未能解决你的问题,请参考以下文章

Flutter - 如何更新用于构建 ListView 的 Future/List 的状态(或值?)(通过 FutureBuilder)

如何减少 Flutter 中 IOS 构建的 .ipa 文件大小?

如何在 Xcode 中设置 Flutter 构建选项

Flutter - 如何在 Listview 构建器顶部添加项目?

用于测试的 Flutter ios 构建

在 iOS 中构建 Flutter 时出现构建错误