From d49d6c9857a2a6e834c9ff60af77f554dd2459d0 Mon Sep 17 00:00:00 2001 From: Dennis Guse Date: Thu, 4 Dec 2025 17:09:31 +0100 Subject: [PATCH] Cleanup: AutoCloseableIterator now handles the cursor. --- .../opentracks/content/data/TestDataUtil.java | 7 ++- .../data/CustomContentProviderUtilsTest.java | 9 ++- .../opentracks/TrackListActivity.java | 6 +- .../opentracks/data/ContentProviderUtils.java | 9 ++- .../opentracks/data/MarkerIterator.java | 56 +----------------- .../opentracks/data/TrackDataHub.java | 3 +- .../opentracks/data/TrackListIterator.java | 54 +---------------- .../opentracks/data/TrackPointIterator.java | 59 +------------------ .../io/file/exporter/CSVTrackExporter.java | 4 +- .../io/file/exporter/GPXTrackExporter.java | 7 ++- .../io/file/exporter/KMLTrackExporter.java | 7 ++- .../io/file/exporter/KMZTrackExporter.java | 4 +- .../io/file/importer/KMZTrackImporter.java | 5 +- .../io/file/importer/TrackImporter.java | 11 +--- .../VoiceAnnouncementManager.java | 4 +- .../opentracks/ui/TrackListAdapter.java | 7 +-- .../ui/intervals/IntervalStatisticsModel.java | 4 +- .../ui/markers/MarkerDetailActivity.java | 26 ++++---- .../util/AutoCloseableIterator.java | 59 ++++++++++++++++--- 19 files changed, 105 insertions(+), 236 deletions(-) diff --git a/src/androidTest/java/de/dennisguse/opentracks/content/data/TestDataUtil.java b/src/androidTest/java/de/dennisguse/opentracks/content/data/TestDataUtil.java index 6e92111f5..d105b760b 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/content/data/TestDataUtil.java +++ b/src/androidTest/java/de/dennisguse/opentracks/content/data/TestDataUtil.java @@ -13,6 +13,8 @@ import java.util.List; import java.util.UUID; import de.dennisguse.opentracks.data.ContentProviderUtils; +import de.dennisguse.opentracks.data.MarkerIterator; +import de.dennisguse.opentracks.data.TrackPointIterator; import de.dennisguse.opentracks.data.models.ActivityType; import de.dennisguse.opentracks.data.models.Altitude; import de.dennisguse.opentracks.data.models.Distance; @@ -23,7 +25,6 @@ import de.dennisguse.opentracks.data.models.Statistics; import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.TrackPoint; import de.dennisguse.opentracks.ui.markers.MarkerUtils; -import de.dennisguse.opentracks.util.AutoCloseableIterator; import de.dennisguse.opentracks.util.FileUtils; public class TestDataUtil { @@ -168,7 +169,7 @@ public class TestDataUtil { } public static List getTrackPoints(ContentProviderUtils contentProviderUtils, Track.Id trackId) { - try (AutoCloseableIterator trackPointIterator = contentProviderUtils.getTrackPointIterator(trackId, null)) { + try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointIterator(trackId, null)) { ArrayList trackPoints = new ArrayList<>(); trackPointIterator.forEachRemaining(trackPoints::add); return trackPoints; @@ -176,7 +177,7 @@ public class TestDataUtil { } public static List getMarkers(ContentProviderUtils contentProviderUtils, Track.Id trackId) { - try (AutoCloseableIterator trackPointIterator = contentProviderUtils.getMarkerIterator(trackId)) { + try (MarkerIterator trackPointIterator = contentProviderUtils.getMarkerIterator(trackId)) { ArrayList markers = new ArrayList<>(); trackPointIterator.forEachRemaining(markers::add); return markers; diff --git a/src/androidTest/java/de/dennisguse/opentracks/data/CustomContentProviderUtilsTest.java b/src/androidTest/java/de/dennisguse/opentracks/data/CustomContentProviderUtilsTest.java index 8b3557c8c..f0532818b 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/data/CustomContentProviderUtilsTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/data/CustomContentProviderUtilsTest.java @@ -67,7 +67,6 @@ import de.dennisguse.opentracks.data.tables.MarkerColumns; import de.dennisguse.opentracks.data.tables.TrackPointsColumns; import de.dennisguse.opentracks.data.tables.TracksColumns; import de.dennisguse.opentracks.stats.SensorStatistics; -import de.dennisguse.opentracks.util.AutoCloseableIterator; import de.dennisguse.opentracks.util.FileUtils; /** @@ -119,7 +118,7 @@ public class CustomContentProviderUtilsTest { private void testIterator(Track.Id trackId, int numPoints) { TrackPoint.Id lastPointId = initializeTrack(trackId, numPoints); List locations = new ArrayList<>(numPoints); - try (AutoCloseableIterator it = contentProviderUtils.getTrackPointIterator(trackId, null)) { + try (TrackPointIterator it = contentProviderUtils.getTrackPointIterator(trackId, null)) { while (it.hasNext()) { TrackPoint trackPoint = it.next(); assertNotNull(trackPoint); @@ -165,7 +164,7 @@ public class CustomContentProviderUtilsTest { // Load all inserted trackPoints. TrackPoint.Id lastPointId = null; int counter = 0; - try (AutoCloseableIterator it = contentProviderUtils.getTrackPointIterator(id, null)) { + try (TrackPointIterator it = contentProviderUtils.getTrackPointIterator(id, null)) { while (it.hasNext()) { TrackPoint trackPoint = it.next(); lastPointId = trackPoint.getId(); @@ -852,7 +851,7 @@ public class CustomContentProviderUtilsTest { TrackPoint.Id startTrackPointId = trackpointIds.get(0); // when - AutoCloseableIterator trackPointIterator = contentProviderUtils.getTrackPointIterator(trackId, trackpointIds.get(0)); + TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointIterator(trackId, trackpointIds.get(0)); // then for (int i = 0; i < trackpointIds.size(); i++) { @@ -1210,7 +1209,7 @@ public class CustomContentProviderUtilsTest { } private TrackPoint getLastValidTrackPoint(Track.Id trackId) { - try (AutoCloseableIterator trackPointsCursor = contentProviderUtils.getTrackPointIterator(trackId, null)) { + try (TrackPointIterator trackPointsCursor = contentProviderUtils.getTrackPointIterator(trackId, null)) { List trackpoints = new ArrayList<>(); while (trackPointsCursor.hasNext()) trackpoints.add(trackPointsCursor.next()); diff --git a/src/main/java/de/dennisguse/opentracks/TrackListActivity.java b/src/main/java/de/dennisguse/opentracks/TrackListActivity.java index bb5924bfc..dc9faa710 100644 --- a/src/main/java/de/dennisguse/opentracks/TrackListActivity.java +++ b/src/main/java/de/dennisguse/opentracks/TrackListActivity.java @@ -45,7 +45,6 @@ import java.util.Arrays; import java.util.Objects; import de.dennisguse.opentracks.data.ContentProviderUtils; -import de.dennisguse.opentracks.data.TrackListIterator; import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.databinding.TrackListBinding; import de.dennisguse.opentracks.sensors.GpsStatusValue; @@ -63,7 +62,6 @@ import de.dennisguse.opentracks.ui.aggregatedStatistics.ConfirmDeleteDialogFragm import de.dennisguse.opentracks.ui.markers.MarkerListActivity; import de.dennisguse.opentracks.ui.util.ActivityUtils; import de.dennisguse.opentracks.ui.util.RecyclerViewSwipeDeleteCallback; -import de.dennisguse.opentracks.util.AutoCloseableIterator; import de.dennisguse.opentracks.util.IntentDashboardUtils; import de.dennisguse.opentracks.util.IntentUtils; import de.dennisguse.opentracks.util.PermissionRequester; @@ -312,9 +310,7 @@ public class TrackListActivity extends AbstractTrackDeleteActivity implements Co viewBinding.trackListToolbar.setTitle(Objects.requireNonNullElseGet(searchQuery, () -> getString(R.string.app_name))); - AutoCloseableIterator tracks = new ContentProviderUtils(this).searchTracks(searchQuery); - - adapter.swapData(tracks); + adapter.swapData(new ContentProviderUtils(this).searchTracks(searchQuery)); } @Override diff --git a/src/main/java/de/dennisguse/opentracks/data/ContentProviderUtils.java b/src/main/java/de/dennisguse/opentracks/data/ContentProviderUtils.java index 31a849e6a..e01fb7c4a 100644 --- a/src/main/java/de/dennisguse/opentracks/data/ContentProviderUtils.java +++ b/src/main/java/de/dennisguse/opentracks/data/ContentProviderUtils.java @@ -56,7 +56,6 @@ import de.dennisguse.opentracks.data.tables.TrackPointsColumns; import de.dennisguse.opentracks.data.tables.TracksColumns; import de.dennisguse.opentracks.stats.SensorStatistics; import de.dennisguse.opentracks.ui.markers.MarkerUtils; -import de.dennisguse.opentracks.util.AutoCloseableIterator; import de.dennisguse.opentracks.util.FileUtils; /** @@ -180,7 +179,7 @@ public class ContentProviderUtils { return tracks; } - public AutoCloseableIterator searchTracks(String searchQuery) { + public TrackListIterator searchTracks(String searchQuery) { // Needed, because MARKER_COUNT is a virtual column and has to be explicitly requested. final String[] PROJECTION = new String[]{ TracksColumns._ID, @@ -401,11 +400,11 @@ public class ContentProviderUtils { return null; } - public AutoCloseableIterator getMarkerIterator(@NonNull Track.Id trackId) { + public MarkerIterator getMarkerIterator(@NonNull Track.Id trackId) { return new MarkerIterator(this, trackId, -1); } - public AutoCloseableIterator getMarkerIterator(@NonNull Track.Id trackId, int maxCount) { + public MarkerIterator getMarkerIterator(@NonNull Track.Id trackId, int maxCount) { return new MarkerIterator(this, trackId, maxCount); } @@ -674,7 +673,7 @@ public class ContentProviderUtils { * @param trackId the track id * @param startTrackPointId the starting trackPoint id. `null` to ignore */ - public AutoCloseableIterator getTrackPointIterator(Track.Id trackId, TrackPoint.Id startTrackPointId) { + public TrackPointIterator getTrackPointIterator(Track.Id trackId, TrackPoint.Id startTrackPointId) { return new TrackPointIterator(this, trackId, startTrackPointId); } diff --git a/src/main/java/de/dennisguse/opentracks/data/MarkerIterator.java b/src/main/java/de/dennisguse/opentracks/data/MarkerIterator.java index 7b5cce296..b4e652735 100644 --- a/src/main/java/de/dennisguse/opentracks/data/MarkerIterator.java +++ b/src/main/java/de/dennisguse/opentracks/data/MarkerIterator.java @@ -3,9 +3,6 @@ package de.dennisguse.opentracks.data; import android.database.Cursor; import androidx.annotation.NonNull; -import androidx.annotation.VisibleForTesting; - -import java.util.NoSuchElementException; import de.dennisguse.opentracks.data.models.Marker; import de.dennisguse.opentracks.data.models.Track; @@ -13,20 +10,16 @@ import de.dennisguse.opentracks.util.AutoCloseableIterator; public class MarkerIterator extends AutoCloseableIterator { - private static final String TAG = MarkerIterator.class.getSimpleName(); - private final ContentProviderUtils contentProviderUtils; - private Cursor cursor; MarkerIterator(ContentProviderUtils contentProviderUtils, Cursor cursor) { + super(cursor); this.contentProviderUtils = contentProviderUtils; - this.cursor = cursor; } MarkerIterator(ContentProviderUtils contentProviderUtils, Track.Id trackId, int maxCount) { + super(contentProviderUtils.getMarkerCursor(trackId, maxCount)); this.contentProviderUtils = contentProviderUtils; - - cursor = contentProviderUtils.getMarkerCursor(trackId, maxCount); } @NonNull @@ -34,49 +27,4 @@ public class MarkerIterator extends AutoCloseableIterator { public Marker get() { return contentProviderUtils.createMarker(cursor); } - - @Override - public boolean hasNext() { - if (cursor == null) { - return false; - } - return !cursor.isLast() && !cursor.isAfterLast(); - } - - @Override - @NonNull - public Marker next() { - if (cursor == null || !cursor.moveToNext()) { - throw new NoSuchElementException(); - } - return get(); - } - - @Override - public int getPosition() { - return cursor.getPosition(); - } - - @Override - public boolean moveToPosition(int position) { - return cursor.moveToPosition(position); - } - - @VisibleForTesting - public int getCount() { - return cursor.getCount(); - } - - @Override - public void close() { - if (cursor != null) { - cursor.close(); - cursor = null; - } - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } } \ No newline at end of file diff --git a/src/main/java/de/dennisguse/opentracks/data/TrackDataHub.java b/src/main/java/de/dennisguse/opentracks/data/TrackDataHub.java index 5f6d78896..f83ac740d 100644 --- a/src/main/java/de/dennisguse/opentracks/data/TrackDataHub.java +++ b/src/main/java/de/dennisguse/opentracks/data/TrackDataHub.java @@ -39,7 +39,6 @@ import de.dennisguse.opentracks.services.RecordingStatus; import de.dennisguse.opentracks.services.TrackRecordingService; import de.dennisguse.opentracks.services.handlers.AltitudeCorrectionManager; import de.dennisguse.opentracks.stats.TrackStatisticsUpdater; -import de.dennisguse.opentracks.util.AutoCloseableIterator; /** * Track data hub. @@ -279,7 +278,7 @@ public class TrackDataHub { } TrackPoint trackPoint = null; - try (AutoCloseableIterator trackPointIterator = contentProviderUtils.getTrackPointIterator(selectedTrackId, next)) { + try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointIterator(selectedTrackId, next)) { long numTotalPoints = trackPointIterator.getCount(); int samplingFrequency = 1 + (int) (numTotalPoints / targetNumPoints); diff --git a/src/main/java/de/dennisguse/opentracks/data/TrackListIterator.java b/src/main/java/de/dennisguse/opentracks/data/TrackListIterator.java index 07ee1971a..041522d4e 100644 --- a/src/main/java/de/dennisguse/opentracks/data/TrackListIterator.java +++ b/src/main/java/de/dennisguse/opentracks/data/TrackListIterator.java @@ -3,12 +3,10 @@ package de.dennisguse.opentracks.data; import android.database.Cursor; import androidx.annotation.NonNull; -import androidx.annotation.VisibleForTesting; import java.time.Duration; import java.time.Instant; import java.time.ZoneOffset; -import java.util.NoSuchElementException; import de.dennisguse.opentracks.data.models.ActivityType; import de.dennisguse.opentracks.data.models.Distance; @@ -18,12 +16,8 @@ import de.dennisguse.opentracks.util.AutoCloseableIterator; public class TrackListIterator extends AutoCloseableIterator { - private static final String TAG = TrackListIterator.class.getSimpleName(); - - private Cursor cursor; - TrackListIterator(Cursor cursor) { - this.cursor = cursor; + super(cursor); } @NonNull @@ -54,51 +48,6 @@ public class TrackListIterator extends AutoCloseableIterator { +public class TrackPointIterator extends AutoCloseableIterator { - private static final String TAG = TrackPointIterator.class.getSimpleName(); private final CachedTrackPointsIndexes indexes; - private Cursor cursor; TrackPointIterator(ContentProviderUtils contentProviderUtils, Track.Id trackId, TrackPoint.Id startTrackPointId) { - cursor = contentProviderUtils.getTrackPointCursor(trackId, startTrackPointId); + super(contentProviderUtils.getTrackPointCursor(trackId, startTrackPointId)); indexes = new CachedTrackPointsIndexes(cursor); } - @Override - public boolean hasNext() { - if (cursor == null) { - return false; - } - return !cursor.isLast() && !cursor.isAfterLast(); - } - @Override @NonNull public TrackPoint get() { return ContentProviderUtils.fillTrackPoint(cursor, indexes); } - - @Override - @NonNull - public TrackPoint next() { - if (cursor == null || !cursor.moveToNext()) { - throw new NoSuchElementException(); - } - return get(); - } - - @Override - public int getPosition() { - return cursor.getPosition(); - } - - @Override - public boolean moveToPosition(int position) { - return cursor.moveToPosition(position); - } - - @VisibleForTesting - public int getCount() { - return cursor.getCount(); - } - - @Override - public void close() { - if (cursor != null) { - cursor.close(); - cursor = null; - } - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } } \ No newline at end of file diff --git a/src/main/java/de/dennisguse/opentracks/io/file/exporter/CSVTrackExporter.java b/src/main/java/de/dennisguse/opentracks/io/file/exporter/CSVTrackExporter.java index 6e337b3d5..80bec7d1e 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/exporter/CSVTrackExporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/exporter/CSVTrackExporter.java @@ -28,10 +28,10 @@ import java.util.Locale; import java.util.function.Function; import de.dennisguse.opentracks.data.ContentProviderUtils; +import de.dennisguse.opentracks.data.TrackPointIterator; import de.dennisguse.opentracks.data.models.Marker; import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.TrackPoint; -import de.dennisguse.opentracks.util.AutoCloseableIterator; import de.dennisguse.opentracks.util.StringUtils; /** @@ -131,7 +131,7 @@ public class CSVTrackExporter implements TrackExporter { } private void writeTrackPoints(List columns, Track track) throws InterruptedException { - try (AutoCloseableIterator trackPointIterator = contentProviderUtils.getTrackPointIterator(track.id(), null)) { + try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointIterator(track.id(), null)) { while (trackPointIterator.hasNext()) { if (Thread.interrupted()) throw new InterruptedException(); diff --git a/src/main/java/de/dennisguse/opentracks/io/file/exporter/GPXTrackExporter.java b/src/main/java/de/dennisguse/opentracks/io/file/exporter/GPXTrackExporter.java index 37587e6eb..31046f28e 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/exporter/GPXTrackExporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/exporter/GPXTrackExporter.java @@ -33,13 +33,14 @@ import java.util.function.Function; import java.util.stream.Stream; import de.dennisguse.opentracks.data.ContentProviderUtils; +import de.dennisguse.opentracks.data.MarkerIterator; +import de.dennisguse.opentracks.data.TrackPointIterator; import de.dennisguse.opentracks.data.models.Distance; import de.dennisguse.opentracks.data.models.Marker; import de.dennisguse.opentracks.data.models.Position; import de.dennisguse.opentracks.data.models.Statistics; import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.TrackPoint; -import de.dennisguse.opentracks.util.AutoCloseableIterator; import de.dennisguse.opentracks.util.StringUtils; /** @@ -128,7 +129,7 @@ public class GPXTrackExporter implements TrackExporter { LinkedList sensorPoints = new LinkedList<>(); - try (AutoCloseableIterator trackPointIterator = contentProviderUtils.getTrackPointIterator(track.id(), null)) { + try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointIterator(track.id(), null)) { while (trackPointIterator.hasNext()) { if (Thread.interrupted()) throw new InterruptedException(); @@ -238,7 +239,7 @@ public class GPXTrackExporter implements TrackExporter { } private void writeMarkers(Track track) throws InterruptedException { - try (AutoCloseableIterator markerIterator = contentProviderUtils.getMarkerIterator(track.id())) { + try (MarkerIterator markerIterator = contentProviderUtils.getMarkerIterator(track.id())) { while (markerIterator.hasNext()) { if (Thread.interrupted()) throw new InterruptedException(); diff --git a/src/main/java/de/dennisguse/opentracks/io/file/exporter/KMLTrackExporter.java b/src/main/java/de/dennisguse/opentracks/io/file/exporter/KMLTrackExporter.java index 88ee42772..274a968d0 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/exporter/KMLTrackExporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/exporter/KMLTrackExporter.java @@ -35,13 +35,14 @@ import java.util.Objects; import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.data.ContentProviderUtils; +import de.dennisguse.opentracks.data.MarkerIterator; +import de.dennisguse.opentracks.data.TrackPointIterator; import de.dennisguse.opentracks.data.models.ActivityType; import de.dennisguse.opentracks.data.models.Marker; import de.dennisguse.opentracks.data.models.Position; import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.TrackPoint; import de.dennisguse.opentracks.ui.markers.MarkerUtils; -import de.dennisguse.opentracks.util.AutoCloseableIterator; import de.dennisguse.opentracks.util.StringUtils; /** @@ -135,7 +136,7 @@ public class KMLTrackExporter implements TrackExporter { private void writeMarkers(Track track) throws InterruptedException { boolean hasMarkers = false; - try (AutoCloseableIterator markerIterator = contentProviderUtils.getMarkerIterator(track.id())) { + try (MarkerIterator markerIterator = contentProviderUtils.getMarkerIterator(track.id())) { while (markerIterator.hasNext()) { if (Thread.interrupted()) throw new InterruptedException(); @@ -156,7 +157,7 @@ public class KMLTrackExporter implements TrackExporter { boolean wroteTrack = false; boolean wroteSegment = false; - try (AutoCloseableIterator trackPointIterator = contentProviderUtils.getTrackPointIterator(track.id(), null)) { + try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointIterator(track.id(), null)) { while (trackPointIterator.hasNext()) { if (Thread.interrupted()) throw new InterruptedException(); diff --git a/src/main/java/de/dennisguse/opentracks/io/file/exporter/KMZTrackExporter.java b/src/main/java/de/dennisguse/opentracks/io/file/exporter/KMZTrackExporter.java index e832104f9..90aa703ef 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/exporter/KMZTrackExporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/exporter/KMZTrackExporter.java @@ -32,10 +32,10 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import de.dennisguse.opentracks.data.ContentProviderUtils; +import de.dennisguse.opentracks.data.MarkerIterator; import de.dennisguse.opentracks.data.models.Marker; import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.ui.markers.MarkerUtils; -import de.dennisguse.opentracks.util.AutoCloseableIterator; import de.dennisguse.opentracks.util.FileUtils; /** @@ -89,7 +89,7 @@ public class KMZTrackExporter implements TrackExporter { private void addImages(Context context, List tracks, ZipOutputStream zipOutputStream) throws InterruptedException, IOException { for (Track track : tracks) { - try (AutoCloseableIterator markerIterator = contentProviderUtils.getMarkerIterator(track.id())) { + try (MarkerIterator markerIterator = contentProviderUtils.getMarkerIterator(track.id())) { while (markerIterator.hasNext()) { if (Thread.interrupted()) throw new InterruptedException(); diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/KMZTrackImporter.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/KMZTrackImporter.java index 120495035..efda49c5b 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/importer/KMZTrackImporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/KMZTrackImporter.java @@ -35,9 +35,8 @@ import java.util.zip.ZipInputStream; import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.data.ContentProviderUtils; -import de.dennisguse.opentracks.data.models.Marker; +import de.dennisguse.opentracks.data.MarkerIterator; import de.dennisguse.opentracks.data.models.Track; -import de.dennisguse.opentracks.util.AutoCloseableIterator; import de.dennisguse.opentracks.util.FileUtils; /** @@ -189,7 +188,7 @@ public class KMZTrackImporter { // 1.- Gets all photo names in the markers of the track identified by id. ContentProviderUtils contentProviderUtils = new ContentProviderUtils(context); List photosName = new ArrayList<>(); - try (AutoCloseableIterator markerIterator = new ContentProviderUtils(context).getMarkerIterator(trackId)) { + try (MarkerIterator markerIterator = new ContentProviderUtils(context).getMarkerIterator(trackId)) { markerIterator.forEachRemaining(marker -> { if (marker.photoUrl() != null) { String photoUrl = Uri.decode(marker.photoUrl().toString()); //TODO Why Uri.decode()? diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java index e06fbb859..6804a4bce 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java @@ -13,6 +13,7 @@ import java.time.Instant; import java.time.ZoneOffset; import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; import java.util.LinkedList; import java.util.List; import java.util.Objects; @@ -134,15 +135,7 @@ public class TrackImporter { trackData.uuid = UUID.randomUUID(); } - trackPoints.sort((o1, o2) -> { - if (o1.getTime().isBefore(o2.getTime())) { - return -1; - } - if (o1.getTime().isAfter(o2.getTime())) { - return 1; - } - return 0; - }); + trackPoints.sort(Comparator.comparing(TrackPoint::getTime)); adjustTrackPoints(); diff --git a/src/main/java/de/dennisguse/opentracks/services/announcement/VoiceAnnouncementManager.java b/src/main/java/de/dennisguse/opentracks/services/announcement/VoiceAnnouncementManager.java index aa11ad0b6..56ac44598 100644 --- a/src/main/java/de/dennisguse/opentracks/services/announcement/VoiceAnnouncementManager.java +++ b/src/main/java/de/dennisguse/opentracks/services/announcement/VoiceAnnouncementManager.java @@ -30,6 +30,7 @@ import java.util.List; import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.data.ContentProviderUtils; +import de.dennisguse.opentracks.data.TrackPointIterator; import de.dennisguse.opentracks.data.models.Distance; import de.dennisguse.opentracks.data.models.Statistics; import de.dennisguse.opentracks.data.models.TrackPoint; @@ -37,7 +38,6 @@ import de.dennisguse.opentracks.services.RecordingData; import de.dennisguse.opentracks.settings.PreferencesUtils; import de.dennisguse.opentracks.stats.SensorStatistics; import de.dennisguse.opentracks.ui.intervals.IntervalStatisticsUpdater; -import de.dennisguse.opentracks.util.AutoCloseableIterator; /** * Execute a periodic task on a time or distance schedule. @@ -149,7 +149,7 @@ public class VoiceAnnouncementManager implements SharedPreferences.OnSharedPrefe } //TODO Avoid reloading (some) TrackPoints just to announce the last interval. - try (AutoCloseableIterator trackPointIterator = contentProviderUtils.getTrackPointIterator(data.track().id(), startTrackPointId)) { + try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointIterator(data.track().id(), startTrackPointId)) { startTrackPointId = intervalStatistics.addTrackPoints(trackPointIterator); Statistics lastInterval = intervalStatistics.getLastInterval(); SensorStatistics sensorStatistics = null; diff --git a/src/main/java/de/dennisguse/opentracks/ui/TrackListAdapter.java b/src/main/java/de/dennisguse/opentracks/ui/TrackListAdapter.java index bf4a99c81..552369312 100644 --- a/src/main/java/de/dennisguse/opentracks/ui/TrackListAdapter.java +++ b/src/main/java/de/dennisguse/opentracks/ui/TrackListAdapter.java @@ -27,7 +27,6 @@ import de.dennisguse.opentracks.services.RecordingStatus; import de.dennisguse.opentracks.settings.UnitSystem; import de.dennisguse.opentracks.ui.util.ActivityUtils; import de.dennisguse.opentracks.ui.util.ListItemUtils; -import de.dennisguse.opentracks.util.AutoCloseableIterator; import de.dennisguse.opentracks.util.IntentUtils; public class TrackListAdapter extends RecyclerView.Adapter implements ActionMode.Callback { @@ -39,7 +38,7 @@ public class TrackListAdapter extends RecyclerView.Adapter cursor; + private TrackListIterator cursor; private boolean selectionMode = false; private ActivityUtils.ContextualActionModeCallback actionModeCallback; private ActionMode actionMode; @@ -85,7 +84,7 @@ public class TrackListAdapter extends RecyclerView.Adapter cursor) { + public void swapData(TrackListIterator cursor) { this.cursor = cursor; this.notifyDataSetChanged(); } @@ -176,7 +175,7 @@ public class TrackListAdapter extends RecyclerView.Adapter cursor) { + public void bind(TrackListIterator cursor) { TrackListIterator.Item tracksListItem = cursor.get(); trackId = tracksListItem.id(); diff --git a/src/main/java/de/dennisguse/opentracks/ui/intervals/IntervalStatisticsModel.java b/src/main/java/de/dennisguse/opentracks/ui/intervals/IntervalStatisticsModel.java index c422ac249..c043f61ee 100644 --- a/src/main/java/de/dennisguse/opentracks/ui/intervals/IntervalStatisticsModel.java +++ b/src/main/java/de/dennisguse/opentracks/ui/intervals/IntervalStatisticsModel.java @@ -17,13 +17,13 @@ import java.util.concurrent.Executor; import java.util.concurrent.Executors; import de.dennisguse.opentracks.data.ContentProviderUtils; +import de.dennisguse.opentracks.data.TrackPointIterator; import de.dennisguse.opentracks.data.models.Distance; import de.dennisguse.opentracks.data.models.Statistics; import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.TrackPoint; import de.dennisguse.opentracks.data.tables.TrackPointsColumns; import de.dennisguse.opentracks.settings.UnitSystem; -import de.dennisguse.opentracks.util.AutoCloseableIterator; /** * This model is used to load intervals for a track. @@ -93,7 +93,7 @@ public class IntervalStatisticsModel extends AndroidViewModel { private void loadIntervalStatistics(Track.Id trackId) { executor.execute(() -> { ContentProviderUtils contentProviderUtils = new ContentProviderUtils(getApplication()); - try (AutoCloseableIterator trackPointIterator = contentProviderUtils.getTrackPointIterator(trackId, lastTrackPointId)) { + try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointIterator(trackId, lastTrackPointId)) { lastTrackPointId = intervalStatistics.addTrackPoints(trackPointIterator); intervalsLiveData.postValue(intervalStatistics.getIntervalList()); } diff --git a/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerDetailActivity.java b/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerDetailActivity.java index 8f24d61df..7bb990480 100644 --- a/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerDetailActivity.java +++ b/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerDetailActivity.java @@ -30,10 +30,10 @@ import androidx.viewpager2.widget.ViewPager2; import de.dennisguse.opentracks.AbstractActivity; import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.data.ContentProviderUtils; +import de.dennisguse.opentracks.data.MarkerIterator; import de.dennisguse.opentracks.data.models.Marker; import de.dennisguse.opentracks.databinding.MarkerDetailActivityBinding; import de.dennisguse.opentracks.ui.markers.DeleteMarkerDialogFragment.DeleteMarkerCaller; -import de.dennisguse.opentracks.util.AutoCloseableIterator; /** * An activity to display marker detail info. @@ -50,7 +50,7 @@ public class MarkerDetailActivity extends AbstractActivity implements DeleteMark private MarkerDetailActivityBinding viewBinding; - private AutoCloseableIterator markerAutoCloseableIterator; + private MarkerIterator markerIterator; @Override protected void onCreate(Bundle bundle) { @@ -66,15 +66,15 @@ public class MarkerDetailActivity extends AbstractActivity implements DeleteMark ContentProviderUtils contentProviderUtils = new ContentProviderUtils(this); Marker marker = contentProviderUtils.getMarker(markerId); - markerAutoCloseableIterator = contentProviderUtils.getMarkerIterator(marker.trackId()); - if (markerAutoCloseableIterator == null) { + markerIterator = contentProviderUtils.getMarkerIterator(marker.trackId()); + if (markerIterator == null) { finish(); } int markerIndex = -1; - while (markerAutoCloseableIterator.hasNext()) { - if (markerId.equals(markerAutoCloseableIterator.next().id())) { - markerIndex = markerAutoCloseableIterator.getPosition(); + while (markerIterator.hasNext()) { + if (markerId.equals(markerIterator.next().id())) { + markerIndex = markerIterator.getPosition(); break; } } @@ -104,8 +104,8 @@ public class MarkerDetailActivity extends AbstractActivity implements DeleteMark super.onDestroy(); viewBinding = null; - if (markerAutoCloseableIterator != null) markerAutoCloseableIterator.close(); - markerAutoCloseableIterator = null; + if (markerIterator != null) markerIterator.close(); + markerIterator = null; } @Override @@ -122,18 +122,18 @@ public class MarkerDetailActivity extends AbstractActivity implements DeleteMark @Override @NonNull public Fragment createFragment(int position) { - markerAutoCloseableIterator.moveToPosition(position); - return MarkerDetailFragment.newInstance(markerAutoCloseableIterator.get(position).id()); + markerIterator.moveToPosition(position); + return MarkerDetailFragment.newInstance(markerIterator.get(position).id()); } @Override public int getItemCount() { - return markerAutoCloseableIterator.getCount(); + return markerIterator.getCount(); } @Nullable public CharSequence getPageTitle(int position) { - return getString(R.string.marker_detail_title, position + 1, getItemCount(), markerAutoCloseableIterator.get().name()); + return getString(R.string.marker_detail_title, position + 1, getItemCount(), markerIterator.get().name()); } } } \ No newline at end of file diff --git a/src/main/java/de/dennisguse/opentracks/util/AutoCloseableIterator.java b/src/main/java/de/dennisguse/opentracks/util/AutoCloseableIterator.java index a9d98fae3..4bfc3b8b0 100644 --- a/src/main/java/de/dennisguse/opentracks/util/AutoCloseableIterator.java +++ b/src/main/java/de/dennisguse/opentracks/util/AutoCloseableIterator.java @@ -1,29 +1,70 @@ package de.dennisguse.opentracks.util; +import android.database.Cursor; + import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; import java.util.Iterator; +import java.util.NoSuchElementException; -//TODO All children use a cursor. Move this shared functionality here. public abstract class AutoCloseableIterator implements Iterator, AutoCloseable { - /** - * Override: AutoClosable.close() throws Exception. - */ - public abstract void close(); + protected Cursor cursor; - public abstract int getPosition(); + public AutoCloseableIterator(Cursor cursor) { + this.cursor = cursor; + } - public abstract boolean moveToPosition(int position); + @Override + @NonNull + public final T next() { + if (cursor == null || !cursor.moveToNext()) { + throw new NoSuchElementException(); + } + return get(); + } + + public final int getPosition() { + return cursor.getPosition(); + } + + public final boolean moveToPosition(int position) { + return cursor.moveToPosition(position); + } + + @Override + public final boolean hasNext() { + if (cursor == null) { + return false; + } + return !cursor.isLast() && !cursor.isAfterLast(); + } @NonNull public abstract T get(); @NonNull - public T get(int position) { + public final T get(int position) { moveToPosition(position); return get(); } - public abstract int getCount(); + @VisibleForTesting + public final int getCount() { + return cursor.getCount(); + } + + @Override + public final void remove() { + throw new UnsupportedOperationException(); + } + + @Override + public final void close() { + if (cursor != null) { + cursor.close(); + cursor = null; + } + } }