refactor: optimize contact fetching and processing for improved performance
All checks were successful
/ mirror (push) Successful in 4s
/ build-stealth (push) Successful in 9m52s
/ build (push) Successful in 9m56s

This commit is contained in:
AlexisDanlos 2025-04-04 14:38:32 +02:00
parent 9e04185da1
commit 8cb206a640
3 changed files with 40 additions and 26 deletions

View File

@ -38,24 +38,28 @@ class _ContactPageState extends State<ContactPage> {
void _toggleFavorite(Contact contact) async { void _toggleFavorite(Contact contact) async {
try { try {
if (await FlutterContacts.requestPermission()) { if (await FlutterContacts.requestPermission()) {
// Avoid full contact fetch by using minimal properties
Contact? fullContact = await FlutterContacts.getContact(contact.id, Contact? fullContact = await FlutterContacts.getContact(contact.id,
withProperties: true, withProperties: true,
withAccounts: true, withAccounts: false, // Don't need accounts for favorite toggle
withPhoto: true, withPhoto: false, // Don't need photo for favorite toggle
withThumbnail: true); withThumbnail: false // Don't need thumbnail for favorite toggle
);
if (fullContact != null) { if (fullContact != null) {
fullContact.isStarred = !fullContact.isStarred; fullContact.isStarred = !fullContact.isStarred;
await FlutterContacts.updateContact(fullContact); await FlutterContacts.updateContact(fullContact);
await _refreshContacts();
} }
await _refreshContacts();
} else { } else {
debugPrint("Could not fetch contact details"); debugPrint("Could not fetch contact details");
} }
} catch (e) { } catch (e) {
debugPrint("Error updating favorite status: $e"); debugPrint("Error updating favorite status: $e");
ScaffoldMessenger.of(context).showSnackBar( if (mounted) {
SnackBar(content: Text('Failed to update favorite status'))); ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Failed to update favorite status')));
}
} }
} }

View File

@ -101,6 +101,10 @@ class _ContactStateState extends State<ContactState> {
void _processContactsInitial(List<Contact> contacts) { void _processContactsInitial(List<Contact> contacts) {
if (!mounted) return; if (!mounted) return;
// Optimize by doing a single pass through contacts instead of multiple iterations
final filteredContacts = contacts.where((contact) => contact.phones.isNotEmpty).toList()
..sort((a, b) => a.displayName.compareTo(b.displayName));
_selfContact = contacts.firstWhere( _selfContact = contacts.firstWhere(
(contact) => contact.displayName.toLowerCase() == "user", (contact) => contact.displayName.toLowerCase() == "user",
orElse: () => Contact(), orElse: () => Contact(),
@ -109,12 +113,9 @@ class _ContactStateState extends State<ContactState> {
if (_selfContact!.phones.isEmpty) { if (_selfContact!.phones.isEmpty) {
_selfContact = null; _selfContact = null;
} }
contacts = contacts.where((contact) => contact.phones.isNotEmpty).toList(); _allContacts = filteredContacts;
contacts.sort((a, b) => a.displayName.compareTo(b.displayName)); _favoriteContacts = filteredContacts.where((contact) => contact.isStarred).toList();
_allContacts = contacts;
_favoriteContacts = contacts.where((contact) => contact.isStarred).toList();
_loading = false; _loading = false;
// Force a rebuild after initialization is complete // Force a rebuild after initialization is complete
@ -128,6 +129,10 @@ class _ContactStateState extends State<ContactState> {
void _processContacts(List<Contact> contacts) { void _processContacts(List<Contact> contacts) {
if (!mounted) return; if (!mounted) return;
// Same optimization as above
final filteredContacts = contacts.where((contact) => contact.phones.isNotEmpty).toList()
..sort((a, b) => a.displayName.compareTo(b.displayName));
_selfContact = contacts.firstWhere( _selfContact = contacts.firstWhere(
(contact) => contact.displayName.toLowerCase() == "user", (contact) => contact.displayName.toLowerCase() == "user",
orElse: () => Contact(), orElse: () => Contact(),
@ -137,12 +142,9 @@ class _ContactStateState extends State<ContactState> {
_selfContact = null; _selfContact = null;
} }
contacts = contacts.where((contact) => contact.phones.isNotEmpty).toList();
contacts.sort((a, b) => a.displayName.compareTo(b.displayName));
setState(() { setState(() {
_allContacts = contacts; _allContacts = filteredContacts;
_favoriteContacts = contacts.where((contact) => contact.isStarred).toList(); _favoriteContacts = filteredContacts.where((contact) => contact.isStarred).toList();
}); });
} }

View File

@ -62,16 +62,24 @@ class _MyHomePageState extends State<MyHomePage>
} }
void _onSearchChanged(String query) { void _onSearchChanged(String query) {
setState(() { if (query.isEmpty) {
if (query.isEmpty) { setState(() {
_contactSuggestions = List.from(_allContacts); // Reset suggestions _contactSuggestions = List.from(_allContacts); // Reset suggestions
} else { });
_contactSuggestions = _allContacts.where((contact) { return;
return contact.displayName }
.toLowerCase()
.contains(query.toLowerCase()); // Convert query to lowercase once for efficiency
}).toList(); final lowerQuery = query.toLowerCase();
}
// Use where with efficient filter
final filtered = _allContacts.where((contact) {
final name = contact.displayName.toLowerCase();
return name.contains(lowerQuery);
}).toList();
setState(() {
_contactSuggestions = filtered;
}); });
} }