TrackListActivity now loads marker count via join rather than a 2nd select.

Fixes #328.
This commit is contained in:
Dennis Guse
2020-11-01 17:34:54 +01:00
parent 43e0f33776
commit 8d141b1324
4 changed files with 43 additions and 58 deletions
@@ -42,11 +42,11 @@ import androidx.core.app.ActivityCompat;
import androidx.cursoradapter.widget.ResourceCursorAdapter;
import androidx.loader.app.LoaderManager;
import androidx.loader.app.LoaderManager.LoaderCallbacks;
import androidx.loader.content.CursorLoader;
import androidx.loader.content.Loader;
import de.dennisguse.opentracks.content.data.Track;
import de.dennisguse.opentracks.content.data.TracksColumns;
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
import de.dennisguse.opentracks.databinding.TrackListBinding;
import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment;
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.StringUtils;
import de.dennisguse.opentracks.util.TrackIconUtils;
import de.dennisguse.opentracks.util.TrackUtils;
/**
* 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();
// The following are set in onCreate
private ContentProviderUtils contentProviderUtils;
private SharedPreferences sharedPreferences;
private TrackRecordingServiceConnection trackRecordingServiceConnection;
private TrackController trackController;
@@ -83,7 +83,11 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
private final LoaderCallbacks<Cursor> loaderCallbacks = new LoaderCallbacks<Cursor>() {
@Override
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
@@ -224,7 +228,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
recordingTrackPaused = PreferencesUtils.isRecordingTrackPausedDefault(this);
contentProviderUtils = new ContentProviderUtils(this);
sharedPreferences = PreferencesUtils.getSharedPreferences(this);
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) {
@Override
public void bindView(View view, Context context, Cursor cursor) {
int idIndex = cursor.getColumnIndex(TracksColumns._ID);
int iconIndex = cursor.getColumnIndex(TracksColumns.ICON);
int nameIndex = cursor.getColumnIndex(TracksColumns.NAME);
int idIndex = cursor.getColumnIndexOrThrow(TracksColumns._ID);
int iconIndex = cursor.getColumnIndexOrThrow(TracksColumns.ICON);
int nameIndex = cursor.getColumnIndexOrThrow(TracksColumns.NAME);
int totalTimeIndex = cursor.getColumnIndexOrThrow(TracksColumns.TOTALTIME);
int totalDistanceIndex = cursor.getColumnIndexOrThrow(TracksColumns.TOTALDISTANCE);
int startTimeIndex = cursor.getColumnIndexOrThrow(TracksColumns.STARTTIME);
int categoryIndex = cursor.getColumnIndex(TracksColumns.CATEGORY);
int descriptionIndex = cursor.getColumnIndex(TracksColumns.DESCRIPTION);
int categoryIndex = cursor.getColumnIndexOrThrow(TracksColumns.CATEGORY);
int descriptionIndex = cursor.getColumnIndexOrThrow(TracksColumns.DESCRIPTION);
int markerCountIndex = cursor.getColumnIndexOrThrow(TracksColumns.MARKER_COUNT);
Track.Id trackId = new Track.Id(cursor.getLong(idIndex));
boolean isRecording = trackId.equals(recordingTrackId);
@@ -272,7 +276,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
String name = cursor.getString(nameIndex);
String totalTime = StringUtils.formatElapsedTime(cursor.getLong(totalTimeIndex));
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);
String category = icon != null && !icon.equals("") ? null : cursor.getString(categoryIndex);
String description = cursor.getString(descriptionIndex);
@@ -35,12 +35,13 @@ public interface TracksColumns extends BaseColumns {
String DEFAULT_SORT_ORDER = _ID;
// Columns
String UUID = "uuid";
String UUID = "uuid"; // identifier to make tracks globally unique (prevent re-import)
String NAME = "name"; // track name
String DESCRIPTION = "description"; // track description
String CATEGORY = "category"; // track activity type
String STARTTIME = "starttime"; // track start time
String STOPTIME = "stoptime"; // track stop time
String MARKER_COUNT = "markerCount"; // the numbers of markers (virtual column)
@Deprecated
String NUMPOINTS = "numpoints"; // number of track points //TODO UNUSED
String TOTALDISTANCE = "totaldistance"; // total distance
@@ -55,25 +56,25 @@ public interface TracksColumns extends BaseColumns {
String ELEVATIONGAIN = "elevationgain"; // elevation gain
String ICON = "icon"; // track activity type icon
String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" // table
+ _ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " // id
+ NAME + " TEXT, " // name
+ DESCRIPTION + " TEXT, " // description
+ CATEGORY + " TEXT, " // category
+ STARTTIME + " INTEGER, " // start time
+ STOPTIME + " INTEGER, " // stop time
+ NUMPOINTS + " INTEGER, " // num points
+ TOTALDISTANCE + " FLOAT, " // total distance
+ TOTALTIME + " INTEGER, " // total time
+ MOVINGTIME + " INTEGER, " // moving time
+ AVGSPEED + " FLOAT, " // average speed
+ AVGMOVINGSPEED + " FLOAT, " // average moving speed
+ MAXSPEED + " FLOAT, " // max speed
+ MINELEVATION + " FLOAT, " // min elevation
+ MAXELEVATION + " FLOAT, " // max elevation
+ ELEVATIONGAIN + " FLOAT, " // elevation gain
+ ICON + " TEXT, " // icon
+ UUID + " BLOB)"; // UUID
String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " ("
+ _ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ NAME + " TEXT, "
+ DESCRIPTION + " TEXT, "
+ CATEGORY + " TEXT, "
+ STARTTIME + " INTEGER, "
+ STOPTIME + " INTEGER, "
+ NUMPOINTS + " INTEGER, "
+ TOTALDISTANCE + " FLOAT, "
+ TOTALTIME + " INTEGER, "
+ MOVINGTIME + " INTEGER, "
+ AVGSPEED + " FLOAT, "
+ AVGMOVINGSPEED + " FLOAT, "
+ MAXSPEED + " FLOAT, "
+ MINELEVATION + " FLOAT, "
+ MAXELEVATION + " FLOAT, "
+ ELEVATIONGAIN + " FLOAT, "
+ ICON + " TEXT, "
+ UUID + " BLOB)";
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.stats.TrackStatistics;
import de.dennisguse.opentracks.util.FileUtils;
import de.dennisguse.opentracks.util.TrackUtils;
import de.dennisguse.opentracks.util.UUIDUtils;
/**
@@ -220,14 +219,6 @@ public class ContentProviderUtils {
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
//TODO Do not use; rather get the proper TrackId (e.g., resume a track might give you some weird effects).
@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) {
if (!trackId.isValid()) {
return 0;
@@ -33,6 +33,8 @@ import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import java.util.Arrays;
import de.dennisguse.opentracks.content.data.MarkerColumns;
import de.dennisguse.opentracks.content.data.TrackPointsColumns;
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)) + ")");
break;
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;
break;
case TRACKS_BY_ID:
@@ -291,11 +297,6 @@ public class CustomContentProvider extends ContentProvider {
return count;
}
/**
* Gets the {@link UrlType} for a url.
*
* @param url the url
*/
@NonNull
private UrlType getUrlType(Uri url) {
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) {
boolean hasLatitude = values.containsKey(TrackPointsColumns.LATITUDE);
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);
}
/**
* Inserts a track.
*
* @param url the content url
* @param contentValues the content values
*/
private Uri insertTrack(Uri url, ContentValues contentValues) {
boolean hasStartTime = contentValues.containsKey(TracksColumns.STARTTIME);
if (!hasStartTime) {