From 3ad36392ee593c49e6a08fb080314c36fd567bf9 Mon Sep 17 00:00:00 2001 From: Pablo Galve Date: Mon, 15 Nov 2021 14:15:52 +0100 Subject: [PATCH 1/2] [Location History] Lag fixed + Improved performance --- Space_Mapper/lib/models/list_view.dart | 6 +++ Space_Mapper/lib/ui/list_view.dart | 70 +++++++++++++++----------- 2 files changed, 48 insertions(+), 28 deletions(-) diff --git a/Space_Mapper/lib/models/list_view.dart b/Space_Mapper/lib/models/list_view.dart index 1f9dde0d..d9a73c3d 100644 --- a/Space_Mapper/lib/models/list_view.dart +++ b/Space_Mapper/lib/models/list_view.dart @@ -22,6 +22,12 @@ class CustomLocationsManager { return ret; } + static void RemoveAllCustomLocations() { + print("Removing " + customLocations.length.toString() + " customLocations"); + customLocations.clear(); + print("All customLocations removed"); + } + /// Makes timestamp readable by a human static String formatTimestamp(String timestamp) { //2021-10-25T21:25:08.210Z <- This is the original format diff --git a/Space_Mapper/lib/ui/list_view.dart b/Space_Mapper/lib/ui/list_view.dart index c5e806b4..4e622c2c 100644 --- a/Space_Mapper/lib/ui/list_view.dart +++ b/Space_Mapper/lib/ui/list_view.dart @@ -57,39 +57,51 @@ class STOListView extends StatefulWidget { class _STOListViewState extends State { late List customLocations = - CustomLocationsManager.fetchAll(sortByNewest: true); + CustomLocationsManager.fetchAll(sortByNewest: false); + + final int maxElements = 25; // Maximum amount of elements displayed on screen + bool recalculationFinished = false; Future recalculateLocations() async { + // Make the current list to be empty. We want to fill it according to our custom parameters + CustomLocationsManager.RemoveAllCustomLocations(); + + // Get a list of locations from the flutter_background_geolocation plugin database List recordedLocations = await bg.BackgroundGeolocation.locations; - /// We check if there are new location entries that we haven't saved in our list - if (recordedLocations.length != customLocations.length) { - for (int i = recordedLocations.length - 1; i >= 0; --i) { - for (int j = customLocations.length - 1; j >= 0; --j) { - if (recordedLocations[i]['uuid'] == - CustomLocationsManager.customLocations[j].getUUID()) continue; - } - //Match not found, we add the location - createCustomLocation( - recordedLocations[i], - await getLocationData(recordedLocations[i]['coords']['latitude'], - recordedLocations[i]['coords']['longitude'])); - - //We update the state to display the new locations - if (this - .mounted) // We check if this screen is active. If we do 'setState' while it's not active, it'll crash (throw exception) - { - setState(() { - customLocations = - CustomLocationsManager.fetchAll(sortByNewest: true); - print("Loading positions: " + - customLocations.length.toString() + - " out of " + - recordedLocations.length.toString()); - }); - } + // n is the minimum value of either the specified maximum amount of elements (maxElements), or the current size of recordedLocations + int n; + if (maxElements <= recordedLocations.length) + n = maxElements; + else + n = recordedLocations.length; + + // Fill the custom locations list, to display beautiful tiles instead of json data + for (int i = 0; i < n; ++i) { + // Check if there's already a location with the same UUID + for (int j = customLocations.length - 1; j >= 0; --j) { + if (recordedLocations[i]['uuid'] == + CustomLocationsManager.customLocations[j].getUUID()) continue; } + // Match not found, we add the location + createCustomLocation( + recordedLocations[i], + await getLocationData(recordedLocations[i]['coords']['latitude'], + recordedLocations[i]['coords']['longitude'])); + } + // Update the state to display the new locations + if (this + .mounted) // Check if this screen is active. If we do 'setState' while it's not active, it'll crash (throw exception) + { + setState(() { + customLocations = CustomLocationsManager.fetchAll(sortByNewest: true); + print("Loading positions: " + + customLocations.length.toString() + + " out of " + + recordedLocations.length.toString()); + }); } + recalculationFinished = true; } @override @@ -105,7 +117,9 @@ class _STOListViewState extends State { title: Text( AppLocalizations.of(context)!.translate("locations_history"))), body: ListView.builder( - itemCount: customLocations.length, + itemCount: customLocations.length < maxElements + ? customLocations.length + : maxElements, itemBuilder: (context, index) { CustomLocation thisLocation = customLocations[index]; return Dismissible( From c5e184c74cc6f5372108b7679e2390b184108e5b Mon Sep 17 00:00:00 2001 From: Pablo Galve Date: Mon, 15 Nov 2021 21:34:04 +0100 Subject: [PATCH 2/2] [Location History] Display Circular Progress Indicator + Optimize performance --- Space_Mapper/lib/models/list_view.dart | 6 +- Space_Mapper/lib/ui/list_view.dart | 85 ++++++++++---------------- 2 files changed, 34 insertions(+), 57 deletions(-) diff --git a/Space_Mapper/lib/models/list_view.dart b/Space_Mapper/lib/models/list_view.dart index d9a73c3d..c409cd4f 100644 --- a/Space_Mapper/lib/models/list_view.dart +++ b/Space_Mapper/lib/models/list_view.dart @@ -22,7 +22,7 @@ class CustomLocationsManager { return ret; } - static void RemoveAllCustomLocations() { + static void removeAllCustomLocations() { print("Removing " + customLocations.length.toString() + " customLocations"); customLocations.clear(); print("All customLocations removed"); @@ -86,8 +86,8 @@ class CustomLocation { /// We need this checker to ensure that the user doesn't send the delete request twice, causing an exception _toDelete = true; await bg.BackgroundGeolocation.destroyLocation(this.getUUID()); - CustomLocationsManager.customLocations - .removeWhere((element) => element.getUUID() == this.getUUID()); + //CustomLocationsManager.customLocations + // .removeWhere((element) => element.getUUID() == this.getUUID()); } } diff --git a/Space_Mapper/lib/ui/list_view.dart b/Space_Mapper/lib/ui/list_view.dart index 4e622c2c..b60e2ef5 100644 --- a/Space_Mapper/lib/ui/list_view.dart +++ b/Space_Mapper/lib/ui/list_view.dart @@ -18,10 +18,11 @@ Future getLocationData(double lat, double long) async { } } -void createCustomLocation(var recordedLocation, Placemark? placemark) { +CustomLocation createCustomLocation( + var recordedLocation, Placemark? placemark) { CustomLocation location = new CustomLocation(); //Add location to list - CustomLocationsManager.customLocations.add(location); + //CustomLocationsManager.customLocations.add(location); //Save data from flutter_background_geolocation library location.setUUID(recordedLocation['uuid']); @@ -46,6 +47,8 @@ void createCustomLocation(var recordedLocation, Placemark? placemark) { location.setStreet(street!); location.setISOCountry(ISO!); } + + return location; } class STOListView extends StatefulWidget { @@ -56,15 +59,13 @@ class STOListView extends StatefulWidget { } class _STOListViewState extends State { - late List customLocations = - CustomLocationsManager.fetchAll(sortByNewest: false); - final int maxElements = 25; // Maximum amount of elements displayed on screen - bool recalculationFinished = false; - Future recalculateLocations() async { + Future> recalculateLocations() async { + List customLocations = []; + // Make the current list to be empty. We want to fill it according to our custom parameters - CustomLocationsManager.RemoveAllCustomLocations(); + //CustomLocationsManager.removeAllCustomLocations(); // Get a list of locations from the flutter_background_geolocation plugin database List recordedLocations = await bg.BackgroundGeolocation.locations; @@ -80,34 +81,23 @@ class _STOListViewState extends State { for (int i = 0; i < n; ++i) { // Check if there's already a location with the same UUID for (int j = customLocations.length - 1; j >= 0; --j) { - if (recordedLocations[i]['uuid'] == - CustomLocationsManager.customLocations[j].getUUID()) continue; + if (recordedLocations[i]['uuid'] == customLocations[j].getUUID()) + continue; //CustomLocationsManager.customLocations[j].getUUID()) continue; } // Match not found, we add the location - createCustomLocation( + CustomLocation newLocation = createCustomLocation( recordedLocations[i], await getLocationData(recordedLocations[i]['coords']['latitude'], recordedLocations[i]['coords']['longitude'])); + customLocations.add(newLocation); } - // Update the state to display the new locations - if (this - .mounted) // Check if this screen is active. If we do 'setState' while it's not active, it'll crash (throw exception) - { - setState(() { - customLocations = CustomLocationsManager.fetchAll(sortByNewest: true); - print("Loading positions: " + - customLocations.length.toString() + - " out of " + - recordedLocations.length.toString()); - }); - } - recalculationFinished = true; + return customLocations; } @override void initState() { super.initState(); - recalculateLocations(); + //recalculateLocations(); } @override @@ -116,36 +106,23 @@ class _STOListViewState extends State { appBar: AppBar( title: Text( AppLocalizations.of(context)!.translate("locations_history"))), - body: ListView.builder( - itemCount: customLocations.length < maxElements - ? customLocations.length - : maxElements, - itemBuilder: (context, index) { - CustomLocation thisLocation = customLocations[index]; - return Dismissible( - child: _tile(thisLocation, context), - background: Container( - child: Container( - margin: EdgeInsets.only(right: 10.0), - alignment: Alignment.centerRight, - child: new LayoutBuilder(builder: (context, constraint) { - return new Icon(Icons.delete_forever, - size: constraint.biggest.height * 0.5); - }), - ), - color: Colors.red, - ), - key: ValueKey(customLocations[index]), - confirmDismiss: (DismissDirection direction) async { - await thisLocation.deleteThisLocation(); - setState(() { - customLocations = - CustomLocationsManager.fetchAll(sortByNewest: true); - thisLocation = customLocations[index]; + body: FutureBuilder>( + future: recalculateLocations(), + builder: (context, snapshot) { + if (!snapshot.hasData) { + return Center( + child: CircularProgressIndicator(), + ); + } + if (snapshot.hasError) { + return Container(); + } + return ListView.builder( + itemCount: snapshot.data!.length, + itemBuilder: (context, index) { + CustomLocation thisLocation = snapshot.data![index]; + return _tile(thisLocation, context); }); - return true; - }, - ); }, )); }