I'm struggling to find a solution to build a widget that displays "Recent Files".
To find the files I have the following
Future<List<File>> findFiles(String prefix) async {
List<File> files = [];
await for (var entity
in directory.list(recursive: true, followLinks: false)) {
File file = File(entity.path);
if (p.extension(file.path) == ".json") {
print("Found in:" entity.path);
if (p.basename(file.path).startsWith(prefix)) files.add(file);
}
}
return files;
}
Then I call it using
var files = await FileManager().findFiles("test");
But I am not sure how to build a list view to display the name of each file as it is a Future and needs awaiting.
Any suggestions?
CodePudding user response:
To display the result of your function in a ListView
, since your function returns a Future
, you should use a FutureBuilder
:
FutureBuilder(
future: findFiles("bla"),
builder: (BuildContext context, AsyncSnapshot<List<File>> snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data?.length,
itemBuilder: (BuildContext context, int index) {
return Text(snapshot.data?[index].path);
},
);
} else if (snapshot.hasError) {
return Text("Error: ${snapshot.error}");
}
return CircularProgressIndicator();
},
)
Here is a YouTube video by the Flutter team explaining FutureBuilder
CodePudding user response:
Here's an example of how you might display a list of strings returned by a Future in a Flutter app using a ListView:
import 'package:flutter/material.dart';
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Future<List<String>> _futureStringList;
@override
void initState() {
super.initState();
_futureStringList = findFiles("...");
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FutureBuilder<List<String>>(
future: _futureStringList,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(snapshot.data[index]),
);
},
);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
// By default, show a loading spinner
return CircularProgressIndicator();
},
),
),
);
}
Future<List<File>> findFiles(String prefix) async {
// Replace this with your actual code to fetch the string list
await Future.delayed(Duration(seconds: 2));
return ['String 1', 'String 2', 'String 3'];
}
}
In this example, We use a FutureBuilder
widget to build the UI based on the state of the Future
. The builder callback is called whenever the Future completes or updates, and we use the snapshot to determine the state of the Future and decide what to display.
If the Future
has completed successfully, the ListView
builder is used to display the list of strings. Each item in the list is represented by a ListTile
widget, with the title set to the corresponding string. If the Future
has failed, an error message is displayed. If the Future is still pending, a loading spinner is displayed.
The findFiles
function is called in the initState
method, which is a lifecycle method that is called when the widget is first created. This is done so that the data is fetched as soon as the widget is initialized, which allows the UI to be built and displayed with the data as soon as possible
Calling the findFiles
function in initState
also ensures that the data is fetched only once, when the widget is first created. If the data were fetched in the build method, it would be fetched again every time the widget is rebuilt, which would be unnecessary and could potentially lead to performance issues.
initState
is called once, before build is called. It is a good place to perform one-time setup of your stateful widget, such as initializing variables, allocating resources and fetching data.
You can also use didChangeDependencies
method, which is similar to initState
, but it will call when some inherited variables change, it would be a good place to perform one-time setup that depend on the inherited widgets, such as fetching data.