首页 > 解决方案 > 如何从未来使用列表并在 listView 中使用它

问题描述

我正在尝试获取某个目录中所有文件的列表。

我从调用的未来函数中获取文件,getUserVideos()如果在函数内部我尝试打印数据,我可以看到结果,但我不能在函数外部使用数据。

class _mediaUtentiState extends State<mediaUtenti> {
  var lightBlue = Color.fromRGBO(0, 197, 205, 1.0);
  var _imagesDir;


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

  List<String> Names = [
    'Abhishek',
    'John',
    'Robert',
    'Shyam',
    'Sita',
    'Gita',
    'Nitish'
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: lightBlue,
      appBar: new AppBar(
        title: Row(
          mainAxisAlignment: MainAxisAlignment.end,
          children: [
            Container(padding: const EdgeInsets.all(8.0), child: Text('Nome')),
            Container(
              child: CircleAvatar(
                backgroundImage: NetworkImage('http://i.pravatar.cc/300'),
              ),
            ),
          ],
        ),
        backgroundColor: purple,
      ),

      body: new Container(
        child: new ListView.builder(
          reverse: false,
          itemBuilder: (_, int index) => EachList(this.Names[index]),
          itemCount: this.Names.length,
        ),
      ),
    );
  }

  Future<String> getUsersVideos() async {
    print('something');
    final Directory extDir = await getExternalStorageDirectory();
    final String dirPath = '${extDir.path}/Movies/Veople';
    final myDir = new Directory(dirPath);
    List<FileSystemEntity> _images;
    _images = myDir.listSync(recursive: true, followLinks: false);
    print(_images.length);
    _imagesDir = _images;
  }
}

class EachList extends StatelessWidget {
  final String name;
  EachList(this.name);
  @override
  Widget build(BuildContext context) {
    return new Card(
      child: new Container(
        padding: EdgeInsets.all(8.0),
        child: new Row(
          children: <Widget>[
            new CircleAvatar(
              child: new Text(name[0]),
            ),
            new Padding(padding: EdgeInsets.only(right: 10.0)),
            new Text(
              name,
              style: TextStyle(fontSize: 20.0),
            )
          ],
        ),
      ),
    );
  }
}

现在我只显示一个名称列表,但我想为路径中的每个文件显示一张卡片。

例如,在getUserVideos()我尝试打印的函数中,imagesDir我得到了正确的结果[File: '/storage/emulated/0/Movies/Veople/1556217605345.mp4', File: '/storage/emulated/0/Movies/Veople/1556217605345.png', File: '/storage/emulated/0/Movies/Veople/1556217632709.mp4', File: ...] 但是我不能以任何方式从该函数中访问 _imageDir。

我确信用几行代码就可以解决这个问题,但现在是 3 个小时,我无法得到解决方案。

谢谢!

标签: asynchronousflutterfuture

解决方案


我认为肯定已经回答了这个问题,但是虽然有很多关于 FutureBuilder 和 Lists 的问题,但没有一个是这样的,或者没有真正得到充分的回答。

这就是我的做法:

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';

Future<List<FileSystemEntity>> _getUsersVideos() async {
  print('something');
  final Directory extDir = await getExternalStorageDirectory();
  final String dirPath = '${extDir.path}/Movies/Veople';
  final myDir = new Directory(dirPath);
  List<FileSystemEntity> _images = myDir.listSync(recursive: true, followLinks: false);
  return _images;
}

class ListFromFuture extends StatefulWidget {
  @override
  _ListFromFutureState createState() => _ListFromFutureState();
}

class _ListFromFutureState extends State<ListFromFuture> {
  Future<List<FileSystemEntity>> future;

  @override
  void initState() {
    super.initState();
    future = _getUsersVideos();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: future,
      builder: (context, snapshot) {
        switch (snapshot.connectionState) {
          case ConnectionState.none:
          case ConnectionState.waiting:
          case ConnectionState.active:
            return Container(
              alignment: Alignment.center,
              child: Text("Loading"),
            );
            break;
          case ConnectionState.done:
            if (snapshot.hasError) {
              // return whatever you'd do for this case, probably an error
              return Container(
                alignment: Alignment.center,
                child: Text("Error: ${snapshot.error}"),
              );
            }
            var data = snapshot.data;
            return new ListView.builder(
              reverse: false,
              itemBuilder: (_, int index) => EachList(data[index]),
              itemCount: data.length,
            );
            break;
        }
      },
    );
  }
}

其中的重要部分是:

  1. future 只是设置它 initState,而不是构建函数。这确保每次构建小部件时都不会调用它
  2. 我处理所有有错误或未来尚未完成的情况。

不过老实说,您的示例实际上非常接近使其正常工作。您所要做的就是将您_imagesDir = images在 a中设置的行换行,setState(() => ...)它应该可以工作(假设列表不返回空)。不过,您还应该检查 _imagesDir == null ,否则您可能会遇到空指针异常。


推荐阅读