So I have managed to fetch the names of the folder and store them in a list. But the problem I am facing is is the list gets called twice so I tend to have duplicate items in my list view. I've asked similar questions about this but the solutions given don't work on my side.
I know the problem is me calling the getFolders()
in the future(which is a bad practice) but that is the only way my code actually work. When I change my list to a type Future I can't use the .add()
functionality.
Below is my code:
Here is where I have declared my list:
class Semester extends StatefulWidget {
final String value;
const Semester({Key? key, required this.value}) : super(key: key);
@override
State<Semester> createState() => _SemesterState();
}
class _SemesterState extends State<Semester> {
late List<String> courses = []; // possible culprit
Future<List<FirebaseFolder>>? listResult;
Future<List<String>> getFolders() async {
final storageRef = FirebaseStorage.instance.ref().child(widget.value);
final listResult = await storageRef.listAll();
for (var prefix in listResult.prefixes) {
courses.add(prefix.name);
}
return courses;
}
@override
void initState() {
// TODO: implement initState
super.initState();
getFolders();
}
So when I change the courses to Future<List> I can't use the courses.add(prefix.name) since it says it is not of type future: And as you can see below I had to use the getFolder() function on my future for it to display contents on my listview, (NOTE: even if I use it on instantiating the result is still same:)
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
leading: kIconButton(),
elevation: 0,
centerTitle: true,
title: const Text("Semester", style: kTitleStyle),
backgroundColor: Colors.white,
),
body: FutureBuilder(
future: getFolders(), // possible culprit
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return const Center(
child: spinkitLines,
);
default:
return Column(
children: [
const SizedBox(
height: 20.0,
),
const Center(
child: Text(
'Tap to choose course',
style: kPlaceholderStyle,
),
),
const SizedBox(
height: 30.0,
),
Expanded(
child: ListView.builder(
itemCount: courses.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: GestureDetector(
onTap: () {
String passedValue = widget.value;
String course = courses[index];
String value = "$passedValue""/""$course";
Get.to(() => CourseContent(value: value, courseChosen: course,));
},
child: Container(
height: 80,
decoration: const BoxDecoration(
color: Colors.black,
borderRadius:
BorderRadius.all(Radius.circular(20)),
boxShadow: [
BoxShadow(
color: Color.fromARGB(75, 0, 0, 0),
blurRadius: 4,
spreadRadius: 0,
offset: Offset(0, 4))
],
),
child: Center(
child: Padding(
padding: const EdgeInsets.all(5.0),
child: Text(
courses[index],
style: kCardTitleStyle,
),
),
),
),
),
);
}),
),
],
);
}
},
),
);
}
}
So I am looking for a way to fetch the list(folders prefixes) and display them in a list view. What I have tried above works but sometimes it displays duplicates which I can tell the getfolder() is being called multiple times.. Help me solve this.
CodePudding user response:
So I came up with a clever and simple solution. I wrapped my for loop with if to check if the array is empty. if not it won't run that code!
late List<String> courses = [];
Future<List<FirebaseFolder>>? listResult;
Future<List<String>> getFolders() async {
final storageRef = FirebaseStorage.instance.ref().child(widget.value);
final listResult = await storageRef.listAll();
if(courses.isEmpty){
for (var prefix in listResult.prefixes) {
courses.add(prefix.name);
}
}
return courses;
}
CodePudding user response:
It is possible to make sure you get the data from snapshot like this way as shown on blow. Note: elements in that child is an example.
if(!snapshot.hasData) {
return Center(
child: const CircularProgressIndicator(
backgroundColor: Colors.lightBlue,
),
);
}