Cleanup: AutoCloseableIterator now handles the cursor.

This commit is contained in:
Dennis Guse
2025-12-04 17:09:31 +01:00
parent 12f0c3313f
commit d49d6c9857
19 changed files with 105 additions and 236 deletions
@@ -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<TrackPoint> getTrackPoints(ContentProviderUtils contentProviderUtils, Track.Id trackId) {
try (AutoCloseableIterator<TrackPoint> trackPointIterator = contentProviderUtils.getTrackPointIterator(trackId, null)) {
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointIterator(trackId, null)) {
ArrayList<TrackPoint> trackPoints = new ArrayList<>();
trackPointIterator.forEachRemaining(trackPoints::add);
return trackPoints;
@@ -176,7 +177,7 @@ public class TestDataUtil {
}
public static List<Marker> getMarkers(ContentProviderUtils contentProviderUtils, Track.Id trackId) {
try (AutoCloseableIterator<Marker> trackPointIterator = contentProviderUtils.getMarkerIterator(trackId)) {
try (MarkerIterator trackPointIterator = contentProviderUtils.getMarkerIterator(trackId)) {
ArrayList<Marker> markers = new ArrayList<>();
trackPointIterator.forEachRemaining(markers::add);
return markers;
@@ -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<TrackPoint> locations = new ArrayList<>(numPoints);
try (AutoCloseableIterator<TrackPoint> 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<TrackPoint> 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<TrackPoint> 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<TrackPoint> trackPointsCursor = contentProviderUtils.getTrackPointIterator(trackId, null)) {
try (TrackPointIterator trackPointsCursor = contentProviderUtils.getTrackPointIterator(trackId, null)) {
List<TrackPoint> trackpoints = new ArrayList<>();
while (trackPointsCursor.hasNext())
trackpoints.add(trackPointsCursor.next());
@@ -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<TrackListIterator.Item> tracks = new ContentProviderUtils(this).searchTracks(searchQuery);
adapter.swapData(tracks);
adapter.swapData(new ContentProviderUtils(this).searchTracks(searchQuery));
}
@Override
@@ -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<TrackListIterator.Item> 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<Marker> getMarkerIterator(@NonNull Track.Id trackId) {
public MarkerIterator getMarkerIterator(@NonNull Track.Id trackId) {
return new MarkerIterator(this, trackId, -1);
}
public AutoCloseableIterator<Marker> 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<TrackPoint> getTrackPointIterator(Track.Id trackId, TrackPoint.Id startTrackPointId) {
public TrackPointIterator getTrackPointIterator(Track.Id trackId, TrackPoint.Id startTrackPointId) {
return new TrackPointIterator(this, trackId, startTrackPointId);
}
@@ -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<Marker> {
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<Marker> {
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();
}
}
@@ -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<TrackPoint> trackPointIterator = contentProviderUtils.getTrackPointIterator(selectedTrackId, next)) {
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointIterator(selectedTrackId, next)) {
long numTotalPoints = trackPointIterator.getCount();
int samplingFrequency = 1 + (int) (numTotalPoints / targetNumPoints);
@@ -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<TrackListIterator.Item> {
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<TrackListIterator.I
);
}
@Override
public boolean hasNext() {
if (cursor == null) {
return false;
}
return !cursor.isLast() && !cursor.isAfterLast();
}
@Override
@NonNull
public Item 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();
}
public record Item(
@NonNull
Track.Id id,
@@ -128,7 +77,6 @@ public class TrackListIterator extends AutoCloseableIterator<TrackListIterator.I
Distance totalDistance,
int markerCount
) {
}
}
@@ -1,78 +1,23 @@
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.Track;
import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.util.AutoCloseableIterator;
/**
* A lightweight wrapper around the original {@link Cursor}.
*/
class TrackPointIterator extends AutoCloseableIterator<TrackPoint> {
public class TrackPointIterator extends AutoCloseableIterator<TrackPoint> {
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();
}
}
@@ -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<Column> columns, Track track) throws InterruptedException {
try (AutoCloseableIterator<TrackPoint> trackPointIterator = contentProviderUtils.getTrackPointIterator(track.id(), null)) {
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointIterator(track.id(), null)) {
while (trackPointIterator.hasNext()) {
if (Thread.interrupted()) throw new InterruptedException();
@@ -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<TrackPoint> sensorPoints = new LinkedList<>();
try (AutoCloseableIterator<TrackPoint> 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<Marker> markerIterator = contentProviderUtils.getMarkerIterator(track.id())) {
try (MarkerIterator markerIterator = contentProviderUtils.getMarkerIterator(track.id())) {
while (markerIterator.hasNext()) {
if (Thread.interrupted()) throw new InterruptedException();
@@ -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<Marker> 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<TrackPoint> trackPointIterator = contentProviderUtils.getTrackPointIterator(track.id(), null)) {
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointIterator(track.id(), null)) {
while (trackPointIterator.hasNext()) {
if (Thread.interrupted()) throw new InterruptedException();
@@ -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<Track> tracks, ZipOutputStream zipOutputStream) throws InterruptedException, IOException {
for (Track track : tracks) {
try (AutoCloseableIterator<Marker> markerIterator = contentProviderUtils.getMarkerIterator(track.id())) {
try (MarkerIterator markerIterator = contentProviderUtils.getMarkerIterator(track.id())) {
while (markerIterator.hasNext()) {
if (Thread.interrupted()) throw new InterruptedException();
@@ -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<String> photosName = new ArrayList<>();
try (AutoCloseableIterator<Marker> 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()?
@@ -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();
@@ -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<TrackPoint> 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;
@@ -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<RecyclerView.ViewHolder> implements ActionMode.Callback {
@@ -39,7 +38,7 @@ public class TrackListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
private final SparseBooleanArray selection = new SparseBooleanArray();
private RecordingStatus recordingStatus;
private UnitSystem unitSystem;
private AutoCloseableIterator<TrackListIterator.Item> 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<RecyclerView.ViewHold
return cursor.getCount();
}
public void swapData(AutoCloseableIterator<TrackListIterator.Item> cursor) {
public void swapData(TrackListIterator cursor) {
this.cursor = cursor;
this.notifyDataSetChanged();
}
@@ -176,7 +175,7 @@ public class TrackListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
}
public void bind(AutoCloseableIterator<TrackListIterator.Item> cursor) {
public void bind(TrackListIterator cursor) {
TrackListIterator.Item tracksListItem = cursor.get();
trackId = tracksListItem.id();
@@ -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<TrackPoint> trackPointIterator = contentProviderUtils.getTrackPointIterator(trackId, lastTrackPointId)) {
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointIterator(trackId, lastTrackPointId)) {
lastTrackPointId = intervalStatistics.addTrackPoints(trackPointIterator);
intervalsLiveData.postValue(intervalStatistics.getIntervalList());
}
@@ -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<Marker> 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());
}
}
}
@@ -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<T> implements Iterator<T>, 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;
}
}
}