forked from upstream-mirrors/OpenTracks
IntervalsFragment doesn't use TrackDataHub anymore. This improve intervals performance. Fixes #808.
This commit is contained in:
@@ -1,19 +1,28 @@
|
||||
package de.dennisguse.opentracks.viewmodels;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.ContentResolver;
|
||||
import android.database.ContentObserver;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.lifecycle.AndroidViewModel;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import de.dennisguse.opentracks.content.data.Distance;
|
||||
import de.dennisguse.opentracks.content.data.Track;
|
||||
import de.dennisguse.opentracks.content.data.TrackPoint;
|
||||
import de.dennisguse.opentracks.content.data.TrackPointsColumns;
|
||||
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
||||
import de.dennisguse.opentracks.content.provider.TrackPointIterator;
|
||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||
import de.dennisguse.opentracks.util.UnitConversions;
|
||||
|
||||
/**
|
||||
* This model is used to load intervals for a track.
|
||||
@@ -21,65 +30,92 @@ import de.dennisguse.opentracks.util.UnitConversions;
|
||||
*/
|
||||
public class IntervalStatisticsModel extends AndroidViewModel {
|
||||
|
||||
private final List<TrackPoint> trackPoints = new ArrayList<>();
|
||||
private static final String TAG = IntervalStatisticsModel.class.getSimpleName();
|
||||
|
||||
private MutableLiveData<List<IntervalStatistics.Interval>> intervalsLiveData;
|
||||
private IntervalStatistics intervalStatistics;
|
||||
private Distance distanceInterval;
|
||||
private Distance minGPSDistance;
|
||||
private final Distance minGPSDistance;
|
||||
private final ContentResolver contentResolver;
|
||||
private ContentObserver trackPointsTableObserver;
|
||||
private TrackPoint.Id lastTrackPointId;
|
||||
|
||||
private final Executor executor = Executors.newSingleThreadExecutor();
|
||||
private HandlerThread handlerThread;
|
||||
private Handler handler;
|
||||
|
||||
public IntervalStatisticsModel(@NonNull Application application) {
|
||||
super(application);
|
||||
minGPSDistance = PreferencesUtils.getRecordingDistanceInterval(PreferencesUtils.getSharedPreferences(application), application);
|
||||
contentResolver = getApplication().getContentResolver();
|
||||
handlerThread = new HandlerThread(TAG);
|
||||
handlerThread.start();
|
||||
handler = new Handler(handlerThread.getLooper());
|
||||
}
|
||||
|
||||
public MutableLiveData<List<IntervalStatistics.Interval>> getIntervalStats(boolean metricUnits, @Nullable IntervalOption interval) {
|
||||
synchronized (trackPoints) {
|
||||
if (intervalsLiveData == null) {
|
||||
if (interval == null) {
|
||||
interval = IntervalOption.OPTION_1;
|
||||
}
|
||||
|
||||
intervalsLiveData = new MutableLiveData<>();
|
||||
distanceInterval = interval.getDistance(metricUnits);
|
||||
loadIntervalStatistics();
|
||||
}
|
||||
return intervalsLiveData;
|
||||
@Override
|
||||
protected void onCleared() {
|
||||
super.onCleared();
|
||||
if (trackPointsTableObserver != null) {
|
||||
contentResolver.unregisterContentObserver(trackPointsTableObserver);
|
||||
trackPointsTableObserver = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void loadIntervalStatistics() {
|
||||
IntervalStatistics intervalStatistics = new IntervalStatistics(trackPoints, distanceInterval, minGPSDistance);
|
||||
intervalsLiveData.postValue(intervalStatistics.getIntervalList());
|
||||
}
|
||||
|
||||
public void add(TrackPoint trackPoint) {
|
||||
synchronized (trackPoints) {
|
||||
trackPoints.add(trackPoint);
|
||||
if (handlerThread != null) {
|
||||
handlerThread.getLooper().quit();
|
||||
handlerThread = null;
|
||||
}
|
||||
handler = null;
|
||||
}
|
||||
|
||||
public void onNewTrackPoints() {
|
||||
synchronized (trackPoints) {
|
||||
if (intervalsLiveData != null) {
|
||||
loadIntervalStatistics();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
synchronized (trackPoints) {
|
||||
trackPoints.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void upload(boolean metricUnits, @Nullable IntervalOption interval) {
|
||||
synchronized (trackPoints) {
|
||||
public MutableLiveData<List<IntervalStatistics.Interval>> getIntervalStats(Track.Id trackId, boolean metricUnits, @Nullable IntervalOption interval) {
|
||||
if (intervalsLiveData == null) {
|
||||
if (interval == null) {
|
||||
interval = IntervalOption.OPTION_1;
|
||||
}
|
||||
|
||||
intervalsLiveData = new MutableLiveData<>();
|
||||
distanceInterval = interval.getDistance(metricUnits);
|
||||
loadIntervalStatistics();
|
||||
intervalStatistics = new IntervalStatistics(distanceInterval, minGPSDistance);
|
||||
|
||||
loadIntervalStatistics(trackId);
|
||||
}
|
||||
|
||||
trackPointsTableObserver = new ContentObserver(handler) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange, Uri uri) {
|
||||
loadIntervalStatistics(trackId);
|
||||
}
|
||||
};
|
||||
contentResolver.registerContentObserver(TrackPointsColumns.CONTENT_URI_BY_TRACKID, false, trackPointsTableObserver);
|
||||
|
||||
return intervalsLiveData;
|
||||
}
|
||||
|
||||
private void loadIntervalStatistics(Track.Id trackId) {
|
||||
executor.execute(() -> {
|
||||
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(getApplication());
|
||||
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, lastTrackPointId)) {
|
||||
lastTrackPointId = intervalStatistics.addTrackPoints(trackPointIterator);
|
||||
intervalsLiveData.postValue(intervalStatistics.getIntervalList());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void onPause() {
|
||||
if (trackPointsTableObserver != null) {
|
||||
contentResolver.unregisterContentObserver(trackPointsTableObserver);
|
||||
}
|
||||
}
|
||||
|
||||
public void update(Track.Id trackId, boolean metricUnits, @Nullable IntervalOption interval) {
|
||||
if (interval == null) {
|
||||
interval = IntervalOption.OPTION_1;
|
||||
}
|
||||
|
||||
lastTrackPointId = null;
|
||||
distanceInterval = interval.getDistance(metricUnits);
|
||||
intervalStatistics = new IntervalStatistics(distanceInterval, minGPSDistance);
|
||||
loadIntervalStatistics(trackId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,6 +143,10 @@ public class IntervalStatisticsModel extends AndroidViewModel {
|
||||
.multipliedBy(multiplier);
|
||||
}
|
||||
|
||||
public boolean sameMultiplier(IntervalOption intervalOption) {
|
||||
return intervalOption != null && this.multiplier == intervalOption.multiplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "" + multiplier; //TODO Somehow IntervalsFragment relies on a parsable Integer.
|
||||
|
||||
Reference in New Issue
Block a user