'Improving performance of ListView.builder with nested FutureBuilders
The ListView.builder of my widget is really laggy and slow when scrolling, especially in debug mode.
class SongsScreen extends StatelessWidget {
const SongsScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final songsProvider = Provider.of<Songs>(context, listen: false);
final songs = songsProvider.getSongs();
return Scaffold(
body: Center(
child: ListView.builder(
primary: true,
itemCount: songs.length,
itemBuilder: (context, index) {
return FutureBuilder<List<dynamic>>(
future: Future.wait([
songsProvider.getTags(songs[index]),
songsProvider.getArtwork(songs[index]),
]),
builder: (ctx, snapshot) {
if (snapshot.hasData) {
return snapshot.data![1] != null
? ListTile(
title: Text(snapshot.data![0].title ?? 'Unknown'),
subtitle: Text(snapshot.data![0].artist ?? 'Unknown'),
leading: ClipRRect(
borderRadius: BorderRadius.circular(4.0),
child: Image.memory(
snapshot.data![1],
fit: BoxFit.fill,
)),
)
: ListTile(
title: Text(songs[index]),
subtitle: const Text('Unknown'),
leading: const CircleAvatar(
child: Icon(Iconsax.music5),
),
);
} else {
return ListTile(
title: Text(songs[index]),
subtitle: const Text('Unknown'),
leading: const CircleAvatar(
child: Icon(Iconsax.music5),
),
);
}
},
);
},
),
),
);
}
}
Is there a possible way to improve the performance? My guess is that the FutureBuilders are slowing down the performance but I could be wrong.
EDIT: I've rearranged the code and now I see a small improvement. But it's still not so smooth.
Solution 1:[1]
You should call the future function to wait for the result, and as soon as it produces the result it calls the builder function where you build the widget.
import 'dart:io';
import 'dart:typed_data';
import 'package:audiotagger/models/tag.dart';
import 'package:flutter/material.dart';
import 'package:iconsax/iconsax.dart';
import 'package:provider/provider.dart';
import 'package:taggr/providers/songs.dart';
class SongsScreen extends StatelessWidget {
const SongsScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final songs = Provider.of<Songs>(context);
return Scaffold(
body: Center(
child: FutureBuilder(
future: songs.getTags(songs.getSongs()),
builder: (ctx, AsyncSnapshot<Tag?> snapshot) {
if (snapshot.hasData) {
return Center(
child: ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(snapshot.data[index]!.title!),
subtitle: Text(snapshot.data[index]!.artist!),
leading: FutureBuilder(
future: songs.getArtwork(songs.getSongs()[index]
.path),
builder: (ctx, AsyncSnapshot<
Uint8List?> artworkSnapshot) {
if (artworkSnapshot.hasData) {
return ClipRRect(
borderRadius: BorderRadius.circular(4.0),
child: Image.memory(artworkSnapshot.data!),
);
} else {
return const CircleAvatar(
child: Icon(Iconsax.music5),
);
}
},
),
);
}
),
);
} else {
return const Text('n');
}
},
),
)
);
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
