如何从将来使用列表并在listView中使用它

时间:2019-04-26 07:22:53

标签: asynchronous flutter future

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

如果我在函数内部尝试打印数据,可以从将来的函数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个小时,我无法解决。

谢谢!

1 个答案:

答案 0 :(得分:1)

我以为可以肯定,这已经被回答了,但是尽管关于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. 将来仅将其设置为initState,而不将其设置为build函数。这样可以确保每次构建小部件时都不会调用它
  2. 我会处理所有可能出错或未来尚未完成的情况。

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