If you're building a music app with on_audio_query, it’s tempting to call querySongs() everywhere—home screen, playlists, search, etc. But this means repeated storage scans → slower UI, battery drain, and unnecessary complexity.
The Wrong Way – Querying Every Time
final OnAudioQuery audioQuery = OnAudioQuery();
Future<List<SongModel>> getSongs() async {
return await audioQuery.querySongs(); // Called in every screen
}
In each screen:
final songs = await getSongs(); // Repeats scan again
The Better Way – Query Once, Share via Provider
- Fetch once in a service (e.g., MusicPlaybackService):
class MusicPlaybackService extends ChangeNotifier {
List<SongModel> _allSongs = [];
Future<void> loadSongs() async {
final OnAudioQuery query = OnAudioQuery();
_allSongs = await query.querySongs();
notifyListeners();
}
List<SongModel> get allSongs => _allSongs;
}
- Provide it globally:
runApp(
ChangeNotifierProvider(
create: (_) {
final service = MusicPlaybackService();
service.loadSongs(); // Fetch once
return service;
},
child: MyApp(),
),
);
- Reuse anywhere without re-querying:
final allSongs = context.watch<MusicPlaybackService>().allSongs;
Benefits
- No repeated disk access.
- Faster UI transitions (playlist, search, player use the same list).
- Centralized state → easier maintenance.