Вячеслав
Вячеслав

Reputation: 825

how to get a list of files from the directory and pass it to the ListView?

I get the list of files from the user's folder. The names of the files I transfer to the ListView.builder. It's work, but I think, this is bad architecture.

A method _getFilesFromDir() call with a high frequency.

How to make the correct list generation, so as not to update the interface without changing the file list?

class CharacteristList extends StatefulWidget {
  @override
  _CharacteristListState createState() => new _CharacteristListState();
}    
class _CharacteristListState extends State<CharacteristList> {
  List<String> filesList = new List<String>();
  List<String> filesL = new List<String>();
  @override    
  void initState() {
    super.initState();
    filesList = [];
  }    
  Future<List<String>> _getFilesFromDir() async{
    filesL = await FilesInDirectory().getFilesFromDir();
    setState(() {
      filesList = filesL;
    });
    return filesList;
  }    
  _getFilesCount(){
    _getFilesFromDir();
    int count = filesList.length;
    return count;
  }    
  @override
  Widget build(BuildContext context) {    
    return new Scaffold(
      appBar: new AppBar(
        title: const Text('Список документов'),
      ),
      body: new Column(
        children: <Widget>[
          new Expanded(
              child: new ListView.builder(
                //TODO не успевает сформировать список файлов
                itemCount: _getFilesCount(),
                itemBuilder: (context, index){
                  return new CharacteristListItem(filesList[index]);
                },
              ),
          ),
        ],
      ),
      floatingActionButton: new FloatingActionButton(
        onPressed: () {
          Navigator.push(context,
              new MaterialPageRoute(builder: (context)
          => new StartScreen()),
          );},
        child: new Icon(Icons.add),
      ),
    );
  }    
}

Upvotes: 29

Views: 56316

Answers (4)

Lakshan Kodithuwakku
Lakshan Kodithuwakku

Reputation: 133

// add dependancy in pubspec.yaml path_provider:

import 'dart:io' as io; import 'package:path_provider/path_provider.dart';

//Declare Globaly
  String directory;
  List file = new List();
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _listofFiles();
  }

// Make New Function
void _listofFiles() async {
    directory = "/storage/emulated/0/Android/data/"; //Give your folder path
    setState(() {
      file = io.Directory("$directory/resume/").listSync();  //use your folder name insted of resume.
    });
  }

// Build Part
@override
  Widget build(BuildContext context) {
    return MaterialApp(
      navigatorKey: navigatorKey,
      title: 'List of Files',
      home: Scaffold(
        appBar: AppBar(
          title: Text("Get List of Files with whole Path"),
        ),
        body: Container(
          child: Column(
            children: <Widget>[
              // your Content if there
              Expanded(
                child: ListView.builder(
                    itemCount: file.length,
                    itemBuilder: (BuildContext context, int index) {
                      return Text(file[index].toString());
                    }),
              )
            ],
          ),
        ),
      ),
    );
  }

Upvotes: 0

Jay Gadariya
Jay Gadariya

Reputation: 1941

  // add dependancy in pubspec.yaml
 path_provider:

 import 'dart:io' as io;
    import 'package:path_provider/path_provider.dart';

    //Declare Globaly
      String directory;
      List file = new List();
      @override
      void initState() {
        // TODO: implement initState
        super.initState();
        _listofFiles();
      }

    // Make New Function
    void _listofFiles() async {
        directory = (await getApplicationDocumentsDirectory()).path;
        setState(() {
          file = io.Directory("$directory/resume/").listSync();  //use your folder name insted of resume.
        });
      }

    // Build Part
    @override
      Widget build(BuildContext context) {
        return MaterialApp(
          navigatorKey: navigatorKey,
          title: 'List of Files',
          home: Scaffold(
            appBar: AppBar(
              title: Text("Get List of Files with whole Path"),
            ),
            body: Container(
              child: Column(
                children: <Widget>[
                  // your Content if there
                  Expanded(
                    child: ListView.builder(
                        itemCount: file.length,
                        itemBuilder: (BuildContext context, int index) {
                          return Text(file[index].toString());
                        }),
                  )
                ],
              ),
            ),
          ),
        );
      }

Upvotes: 33

Вячеслав
Вячеслав

Reputation: 825

I changed the architecture of the class - I used FutureBuilder.

class _CharacteristListState extends State<CharacteristList> {

  @override
  Widget build(BuildContext context) {

    return new Scaffold(
      appBar: new AppBar(
        title: const Text('Список документов'),
      ),
      body: new Center(
        child: new Column(
          children: <Widget>[
            new FutureBuilder(
                future: _inFutureList(),
                builder: (BuildContext context, AsyncSnapshot snapshot) {
                  if(snapshot.connectionState == ConnectionState.waiting){
                    return new Text('Data is loading...');
                  }
                  else{
                    return customBuild(context, snapshot);
                  }
                }
                )
          ],
        ),
      ),
      floatingActionButton: new FloatingActionButton(
        onPressed: () {
          Navigator.push(context,
              new MaterialPageRoute(builder: (context)
          => new StartScreen()),
          );},
        child: new Icon(Icons.add),
      ),
    );
  }

  Widget customBuild(BuildContext context, AsyncSnapshot snapshot){
    List<String> values = snapshot.data;
    return new Container(
      child: new Expanded(
        child: new ListView.builder(
          itemCount: values.length,
          itemBuilder: (context, index){
            return new CharacteristListItem(values[index]);
          },
        ),
      )
    );
  }

  Future<List<String>>_inFutureList() async{
    var filesList = new List<String>();
    filesList = await FilesInDirectory().getFilesFromDir();
    await new Future.delayed(new Duration(milliseconds: 500));
    return filesList;
  }

}

Upvotes: 1

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

Reputation: 657158

Don't call _getFilesCount() in build(). build() can be called very frequently. Call it in initState() and store the result instead of re-reading over and over again.

Upvotes: 7

Related Questions