I want to create a widget that lists all of the sub directories in a given directory. I have elected to use StreamBuilder
to achieve this, here is my app:
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart' as path;
void main() {
runApp(ArmyMakerApp());
}
class ArmyMakerApp extends StatelessWidget {
const ArmyMakerApp({super.key});
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => ArmyMakerAppState(),
child: MaterialApp(
title: 'Army Maker',
theme: ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
),
home: ArmiesPage(),
),
);
}
}
class ArmyMakerAppState extends ChangeNotifier {}
class ArmiesPage extends StatefulWidget {
@override
State<ArmiesPage> createState() => _ArmiesPageState();
}
class _ArmiesPageState extends State<ArmiesPage> {
Stream<FileSystemEntity>? _repositories;
List<FileSystemEntity> _repositoriesList = [];
_ArmiesPageState() {
getRepositoriesDirectory().then((repositoriesDirectory) => setState(() {
_repositories = repositoriesDirectory.list(recursive: false);
}));
}
@override
Widget build(BuildContext context) {
final Stream<FileSystemEntity>? repositories = _repositories;
return StreamBuilder(
stream: repositories,
builder:
(BuildContext context, AsyncSnapshot<FileSystemEntity> snapshot) {
if (snapshot.hasData) {
_repositoriesList.add(snapshot.data!);
}
return Scaffold(
body: ListView.builder(
itemCount: _repositoriesList.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text(_repositoriesList[index].path));
}),
);
});
}
}
Future<Directory> getDocumentsDirectory() async {
final rootDocumentsDirectory = await getApplicationDocumentsDirectory();
final documentsDirectory =
Directory(path.join(rootDocumentsDirectory.path, "army_maker"));
return documentsDirectory;
}
Future<Directory> getRepositoriesDirectory() async {
final directory = await getDocumentsDirectory();
return Directory(path.join(directory.path, 'repositories'));
}
In theory, repositoriesList
should be extended to contain all the files in ~/Documents/army_maker/repositories
. But not only does this not happen but the behavior of my widget appears to be completely arbitrary. For testing purposes I have created a single subdirectory ~/Documents/army_maker/repositories/foo
. Now when, when I start my app, _ArmiesPageState.build
is called four times in total, two of which add foo
to _repositoriesList
. I would expect build
to only be called once. Why is this happening and how can I fix it?