forked from upstream-mirrors/OpenTracks
TrackListActivity now loads marker count via join rather than a 2nd select.
Fixes #328.
This commit is contained in:
@@ -42,11 +42,11 @@ import androidx.core.app.ActivityCompat;
|
|||||||
import androidx.cursoradapter.widget.ResourceCursorAdapter;
|
import androidx.cursoradapter.widget.ResourceCursorAdapter;
|
||||||
import androidx.loader.app.LoaderManager;
|
import androidx.loader.app.LoaderManager;
|
||||||
import androidx.loader.app.LoaderManager.LoaderCallbacks;
|
import androidx.loader.app.LoaderManager.LoaderCallbacks;
|
||||||
|
import androidx.loader.content.CursorLoader;
|
||||||
import androidx.loader.content.Loader;
|
import androidx.loader.content.Loader;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.content.data.Track;
|
import de.dennisguse.opentracks.content.data.Track;
|
||||||
import de.dennisguse.opentracks.content.data.TracksColumns;
|
import de.dennisguse.opentracks.content.data.TracksColumns;
|
||||||
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
|
||||||
import de.dennisguse.opentracks.databinding.TrackListBinding;
|
import de.dennisguse.opentracks.databinding.TrackListBinding;
|
||||||
import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment;
|
import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment;
|
||||||
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
||||||
@@ -60,6 +60,7 @@ import de.dennisguse.opentracks.util.ListItemUtils;
|
|||||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||||
import de.dennisguse.opentracks.util.StringUtils;
|
import de.dennisguse.opentracks.util.StringUtils;
|
||||||
import de.dennisguse.opentracks.util.TrackIconUtils;
|
import de.dennisguse.opentracks.util.TrackIconUtils;
|
||||||
|
import de.dennisguse.opentracks.util.TrackUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An activity displaying a list of tracks.
|
* An activity displaying a list of tracks.
|
||||||
@@ -71,7 +72,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
private static final String TAG = TrackListActivity.class.getSimpleName();
|
private static final String TAG = TrackListActivity.class.getSimpleName();
|
||||||
|
|
||||||
// The following are set in onCreate
|
// The following are set in onCreate
|
||||||
private ContentProviderUtils contentProviderUtils;
|
|
||||||
private SharedPreferences sharedPreferences;
|
private SharedPreferences sharedPreferences;
|
||||||
private TrackRecordingServiceConnection trackRecordingServiceConnection;
|
private TrackRecordingServiceConnection trackRecordingServiceConnection;
|
||||||
private TrackController trackController;
|
private TrackController trackController;
|
||||||
@@ -83,7 +83,11 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
private final LoaderCallbacks<Cursor> loaderCallbacks = new LoaderCallbacks<Cursor>() {
|
private final LoaderCallbacks<Cursor> loaderCallbacks = new LoaderCallbacks<Cursor>() {
|
||||||
@Override
|
@Override
|
||||||
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
|
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
|
||||||
return ContentProviderUtils.getTracksCursorLoader(TrackListActivity.this);
|
String[] PROJECTION = new String[]{TracksColumns._ID, TracksColumns.NAME,
|
||||||
|
TracksColumns.DESCRIPTION, TracksColumns.CATEGORY, TracksColumns.STARTTIME,
|
||||||
|
TracksColumns.TOTALDISTANCE, TracksColumns.TOTALTIME, TracksColumns.ICON, "markerCount"};
|
||||||
|
|
||||||
|
return new CursorLoader(TrackListActivity.this, TracksColumns.CONTENT_URI, PROJECTION, null, null, TrackUtils.TRACK_SORT_ORDER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -224,7 +228,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
|
|
||||||
recordingTrackPaused = PreferencesUtils.isRecordingTrackPausedDefault(this);
|
recordingTrackPaused = PreferencesUtils.isRecordingTrackPausedDefault(this);
|
||||||
|
|
||||||
contentProviderUtils = new ContentProviderUtils(this);
|
|
||||||
sharedPreferences = PreferencesUtils.getSharedPreferences(this);
|
sharedPreferences = PreferencesUtils.getSharedPreferences(this);
|
||||||
|
|
||||||
trackRecordingServiceConnection = new TrackRecordingServiceConnection(bindChangedCallback);
|
trackRecordingServiceConnection = new TrackRecordingServiceConnection(bindChangedCallback);
|
||||||
@@ -256,14 +259,15 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
resourceCursorAdapter = new ResourceCursorAdapter(this, R.layout.list_item, null, 0) {
|
resourceCursorAdapter = new ResourceCursorAdapter(this, R.layout.list_item, null, 0) {
|
||||||
@Override
|
@Override
|
||||||
public void bindView(View view, Context context, Cursor cursor) {
|
public void bindView(View view, Context context, Cursor cursor) {
|
||||||
int idIndex = cursor.getColumnIndex(TracksColumns._ID);
|
int idIndex = cursor.getColumnIndexOrThrow(TracksColumns._ID);
|
||||||
int iconIndex = cursor.getColumnIndex(TracksColumns.ICON);
|
int iconIndex = cursor.getColumnIndexOrThrow(TracksColumns.ICON);
|
||||||
int nameIndex = cursor.getColumnIndex(TracksColumns.NAME);
|
int nameIndex = cursor.getColumnIndexOrThrow(TracksColumns.NAME);
|
||||||
int totalTimeIndex = cursor.getColumnIndexOrThrow(TracksColumns.TOTALTIME);
|
int totalTimeIndex = cursor.getColumnIndexOrThrow(TracksColumns.TOTALTIME);
|
||||||
int totalDistanceIndex = cursor.getColumnIndexOrThrow(TracksColumns.TOTALDISTANCE);
|
int totalDistanceIndex = cursor.getColumnIndexOrThrow(TracksColumns.TOTALDISTANCE);
|
||||||
int startTimeIndex = cursor.getColumnIndexOrThrow(TracksColumns.STARTTIME);
|
int startTimeIndex = cursor.getColumnIndexOrThrow(TracksColumns.STARTTIME);
|
||||||
int categoryIndex = cursor.getColumnIndex(TracksColumns.CATEGORY);
|
int categoryIndex = cursor.getColumnIndexOrThrow(TracksColumns.CATEGORY);
|
||||||
int descriptionIndex = cursor.getColumnIndex(TracksColumns.DESCRIPTION);
|
int descriptionIndex = cursor.getColumnIndexOrThrow(TracksColumns.DESCRIPTION);
|
||||||
|
int markerCountIndex = cursor.getColumnIndexOrThrow(TracksColumns.MARKER_COUNT);
|
||||||
|
|
||||||
Track.Id trackId = new Track.Id(cursor.getLong(idIndex));
|
Track.Id trackId = new Track.Id(cursor.getLong(idIndex));
|
||||||
boolean isRecording = trackId.equals(recordingTrackId);
|
boolean isRecording = trackId.equals(recordingTrackId);
|
||||||
@@ -272,7 +276,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
String name = cursor.getString(nameIndex);
|
String name = cursor.getString(nameIndex);
|
||||||
String totalTime = StringUtils.formatElapsedTime(cursor.getLong(totalTimeIndex));
|
String totalTime = StringUtils.formatElapsedTime(cursor.getLong(totalTimeIndex));
|
||||||
String totalDistance = StringUtils.formatDistance(TrackListActivity.this, cursor.getDouble(totalDistanceIndex), metricUnits);
|
String totalDistance = StringUtils.formatDistance(TrackListActivity.this, cursor.getDouble(totalDistanceIndex), metricUnits);
|
||||||
int markerCount = contentProviderUtils.getMarkerCount(trackId);
|
int markerCount = cursor.getInt(markerCountIndex);
|
||||||
long startTime = cursor.getLong(startTimeIndex);
|
long startTime = cursor.getLong(startTimeIndex);
|
||||||
String category = icon != null && !icon.equals("") ? null : cursor.getString(categoryIndex);
|
String category = icon != null && !icon.equals("") ? null : cursor.getString(categoryIndex);
|
||||||
String description = cursor.getString(descriptionIndex);
|
String description = cursor.getString(descriptionIndex);
|
||||||
|
|||||||
@@ -35,12 +35,13 @@ public interface TracksColumns extends BaseColumns {
|
|||||||
String DEFAULT_SORT_ORDER = _ID;
|
String DEFAULT_SORT_ORDER = _ID;
|
||||||
|
|
||||||
// Columns
|
// Columns
|
||||||
String UUID = "uuid";
|
String UUID = "uuid"; // identifier to make tracks globally unique (prevent re-import)
|
||||||
String NAME = "name"; // track name
|
String NAME = "name"; // track name
|
||||||
String DESCRIPTION = "description"; // track description
|
String DESCRIPTION = "description"; // track description
|
||||||
String CATEGORY = "category"; // track activity type
|
String CATEGORY = "category"; // track activity type
|
||||||
String STARTTIME = "starttime"; // track start time
|
String STARTTIME = "starttime"; // track start time
|
||||||
String STOPTIME = "stoptime"; // track stop time
|
String STOPTIME = "stoptime"; // track stop time
|
||||||
|
String MARKER_COUNT = "markerCount"; // the numbers of markers (virtual column)
|
||||||
@Deprecated
|
@Deprecated
|
||||||
String NUMPOINTS = "numpoints"; // number of track points //TODO UNUSED
|
String NUMPOINTS = "numpoints"; // number of track points //TODO UNUSED
|
||||||
String TOTALDISTANCE = "totaldistance"; // total distance
|
String TOTALDISTANCE = "totaldistance"; // total distance
|
||||||
@@ -55,25 +56,25 @@ public interface TracksColumns extends BaseColumns {
|
|||||||
String ELEVATIONGAIN = "elevationgain"; // elevation gain
|
String ELEVATIONGAIN = "elevationgain"; // elevation gain
|
||||||
String ICON = "icon"; // track activity type icon
|
String ICON = "icon"; // track activity type icon
|
||||||
|
|
||||||
String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" // table
|
String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " ("
|
||||||
+ _ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " // id
|
+ _ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||||
+ NAME + " TEXT, " // name
|
+ NAME + " TEXT, "
|
||||||
+ DESCRIPTION + " TEXT, " // description
|
+ DESCRIPTION + " TEXT, "
|
||||||
+ CATEGORY + " TEXT, " // category
|
+ CATEGORY + " TEXT, "
|
||||||
+ STARTTIME + " INTEGER, " // start time
|
+ STARTTIME + " INTEGER, "
|
||||||
+ STOPTIME + " INTEGER, " // stop time
|
+ STOPTIME + " INTEGER, "
|
||||||
+ NUMPOINTS + " INTEGER, " // num points
|
+ NUMPOINTS + " INTEGER, "
|
||||||
+ TOTALDISTANCE + " FLOAT, " // total distance
|
+ TOTALDISTANCE + " FLOAT, "
|
||||||
+ TOTALTIME + " INTEGER, " // total time
|
+ TOTALTIME + " INTEGER, "
|
||||||
+ MOVINGTIME + " INTEGER, " // moving time
|
+ MOVINGTIME + " INTEGER, "
|
||||||
+ AVGSPEED + " FLOAT, " // average speed
|
+ AVGSPEED + " FLOAT, "
|
||||||
+ AVGMOVINGSPEED + " FLOAT, " // average moving speed
|
+ AVGMOVINGSPEED + " FLOAT, "
|
||||||
+ MAXSPEED + " FLOAT, " // max speed
|
+ MAXSPEED + " FLOAT, "
|
||||||
+ MINELEVATION + " FLOAT, " // min elevation
|
+ MINELEVATION + " FLOAT, "
|
||||||
+ MAXELEVATION + " FLOAT, " // max elevation
|
+ MAXELEVATION + " FLOAT, "
|
||||||
+ ELEVATIONGAIN + " FLOAT, " // elevation gain
|
+ ELEVATIONGAIN + " FLOAT, "
|
||||||
+ ICON + " TEXT, " // icon
|
+ ICON + " TEXT, "
|
||||||
+ UUID + " BLOB)"; // UUID
|
+ UUID + " BLOB)";
|
||||||
|
|
||||||
String CREATE_TABLE_INDEX = "CREATE UNIQUE INDEX " + TABLE_NAME + "_" + UUID + "_index ON " + TABLE_NAME + "(" + UUID + ")";
|
String CREATE_TABLE_INDEX = "CREATE UNIQUE INDEX " + TABLE_NAME + "_" + UUID + "_index ON " + TABLE_NAME + "(" + UUID + ")";
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ import de.dennisguse.opentracks.content.data.TrackPointsColumns;
|
|||||||
import de.dennisguse.opentracks.content.data.TracksColumns;
|
import de.dennisguse.opentracks.content.data.TracksColumns;
|
||||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||||
import de.dennisguse.opentracks.util.FileUtils;
|
import de.dennisguse.opentracks.util.FileUtils;
|
||||||
import de.dennisguse.opentracks.util.TrackUtils;
|
|
||||||
import de.dennisguse.opentracks.util.UUIDUtils;
|
import de.dennisguse.opentracks.util.UUIDUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -220,14 +219,6 @@ public class ContentProviderUtils {
|
|||||||
return tracks;
|
return tracks;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Loader<Cursor> getTracksCursorLoader(Context context) {
|
|
||||||
String[] PROJECTION = new String[]{TracksColumns._ID, TracksColumns.NAME,
|
|
||||||
TracksColumns.DESCRIPTION, TracksColumns.CATEGORY, TracksColumns.STARTTIME,
|
|
||||||
TracksColumns.TOTALDISTANCE, TracksColumns.TOTALTIME, TracksColumns.ICON};
|
|
||||||
|
|
||||||
return new CursorLoader(context, TracksColumns.CONTENT_URI, PROJECTION, null, null, TrackUtils.TRACK_SORT_ORDER);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
//TODO Do not use; rather get the proper TrackId (e.g., resume a track might give you some weird effects).
|
//TODO Do not use; rather get the proper TrackId (e.g., resume a track might give you some weird effects).
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@@ -498,7 +489,7 @@ public class ContentProviderUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated //TODO Expose information via Cursor
|
@Deprecated //TODO TracksColumns.MARKER_COUNT while querying for tracks
|
||||||
public int getMarkerCount(Track.Id trackId) {
|
public int getMarkerCount(Track.Id trackId) {
|
||||||
if (!trackId.isValid()) {
|
if (!trackId.isValid()) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ import android.util.Log;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.content.data.MarkerColumns;
|
import de.dennisguse.opentracks.content.data.MarkerColumns;
|
||||||
import de.dennisguse.opentracks.content.data.TrackPointsColumns;
|
import de.dennisguse.opentracks.content.data.TrackPointsColumns;
|
||||||
import de.dennisguse.opentracks.content.data.TracksColumns;
|
import de.dennisguse.opentracks.content.data.TracksColumns;
|
||||||
@@ -210,7 +212,11 @@ public class CustomContentProvider extends ContentProvider {
|
|||||||
queryBuilder.appendWhere(TrackPointsColumns.TRACKID + " IN (" + TextUtils.join(SQL_LIST_DELIMITER, ContentProviderUtils.parseTrackIdsFromUri(url)) + ")");
|
queryBuilder.appendWhere(TrackPointsColumns.TRACKID + " IN (" + TextUtils.join(SQL_LIST_DELIMITER, ContentProviderUtils.parseTrackIdsFromUri(url)) + ")");
|
||||||
break;
|
break;
|
||||||
case TRACKS:
|
case TRACKS:
|
||||||
queryBuilder.setTables(TracksColumns.TABLE_NAME);
|
if (projection != null && Arrays.asList(projection).contains(TracksColumns.MARKER_COUNT)) {
|
||||||
|
queryBuilder.setTables(TracksColumns.TABLE_NAME + " LEFT OUTER JOIN (SELECT " + MarkerColumns.TRACKID + " AS markerTrackId, COUNT(*) AS " + TracksColumns.MARKER_COUNT + " FROM " + MarkerColumns.TABLE_NAME + " GROUP BY " + MarkerColumns.TRACKID + ") ON (" + TracksColumns.TABLE_NAME + "." + TracksColumns._ID + "= markerTrackId)");
|
||||||
|
} else {
|
||||||
|
queryBuilder.setTables(TracksColumns.TABLE_NAME);
|
||||||
|
}
|
||||||
sortOrder = sort != null ? sort : TracksColumns.DEFAULT_SORT_ORDER;
|
sortOrder = sort != null ? sort : TracksColumns.DEFAULT_SORT_ORDER;
|
||||||
break;
|
break;
|
||||||
case TRACKS_BY_ID:
|
case TRACKS_BY_ID:
|
||||||
@@ -291,11 +297,6 @@ public class CustomContentProvider extends ContentProvider {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the {@link UrlType} for a url.
|
|
||||||
*
|
|
||||||
* @param url the url
|
|
||||||
*/
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private UrlType getUrlType(Uri url) {
|
private UrlType getUrlType(Uri url) {
|
||||||
UrlType[] urlTypes = UrlType.values();
|
UrlType[] urlTypes = UrlType.values();
|
||||||
@@ -327,12 +328,6 @@ public class CustomContentProvider extends ContentProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Inserts a track point.
|
|
||||||
*
|
|
||||||
* @param url the content url
|
|
||||||
* @param values the content values
|
|
||||||
*/
|
|
||||||
private Uri insertTrackPoint(Uri url, ContentValues values) {
|
private Uri insertTrackPoint(Uri url, ContentValues values) {
|
||||||
boolean hasLatitude = values.containsKey(TrackPointsColumns.LATITUDE);
|
boolean hasLatitude = values.containsKey(TrackPointsColumns.LATITUDE);
|
||||||
boolean hasLongitude = values.containsKey(TrackPointsColumns.LONGITUDE);
|
boolean hasLongitude = values.containsKey(TrackPointsColumns.LONGITUDE);
|
||||||
@@ -347,12 +342,6 @@ public class CustomContentProvider extends ContentProvider {
|
|||||||
throw new SQLiteException("Failed to insert a track point " + url);
|
throw new SQLiteException("Failed to insert a track point " + url);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Inserts a track.
|
|
||||||
*
|
|
||||||
* @param url the content url
|
|
||||||
* @param contentValues the content values
|
|
||||||
*/
|
|
||||||
private Uri insertTrack(Uri url, ContentValues contentValues) {
|
private Uri insertTrack(Uri url, ContentValues contentValues) {
|
||||||
boolean hasStartTime = contentValues.containsKey(TracksColumns.STARTTIME);
|
boolean hasStartTime = contentValues.containsKey(TracksColumns.STARTTIME);
|
||||||
if (!hasStartTime) {
|
if (!hasStartTime) {
|
||||||
|
|||||||
Reference in New Issue
Block a user