IntervalsFragment doesn't use TrackDataHub anymore. This improve intervals performance. Fixes #808.

This commit is contained in:
Román Martínez
2021-06-03 17:16:03 +02:00
parent 4c68592a0c
commit 838671e2ce
11 changed files with 166 additions and 163 deletions
@@ -4,7 +4,6 @@ package de.dennisguse.opentracks;
import android.app.ActivityManager;
import android.app.Instrumentation;
import android.content.Context;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
@@ -52,7 +52,8 @@ public class AnnouncementUtilsTest {
stats.setTotalAltitudeGain(6000f);
List<TrackPoint> trackPoints = TestDataUtil.createTrack(new Track.Id(System.currentTimeMillis()), 10).second;
IntervalStatistics intervalStatistics = new IntervalStatistics(trackPoints, Distance.of(1000), Distance.of(0));
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(1000), Distance.of(0));
intervalStatistics.addTrackPoints(trackPoints);
IntervalStatistics.Interval lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1);
// when
@@ -88,7 +89,8 @@ public class AnnouncementUtilsTest {
stats.setTotalAltitudeGain(6000f);
List<TrackPoint> trackPoints = TestDataUtil.createTrack(new Track.Id(System.currentTimeMillis()), 10).second;
IntervalStatistics intervalStatistics = new IntervalStatistics(trackPoints, Distance.of(1000));
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(1000), Distance.of(0));
intervalStatistics.addTrackPoints(trackPoints);
IntervalStatistics.Interval lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1);
// when
@@ -124,7 +126,8 @@ public class AnnouncementUtilsTest {
stats.setTotalAltitudeGain(6000f);
List<TrackPoint> trackPoints = TestDataUtil.createTrack(new Track.Id(System.currentTimeMillis()), 10).second;
IntervalStatistics intervalStatistics = new IntervalStatistics(trackPoints, Distance.of(1000));
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(1000), Distance.of(0));
intervalStatistics.addTrackPoints(trackPoints);
IntervalStatistics.Interval lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1);
// when
@@ -160,7 +163,8 @@ public class AnnouncementUtilsTest {
stats.setTotalAltitudeGain(6000f);
List<TrackPoint> trackPoints = TestDataUtil.createTrack(new Track.Id(System.currentTimeMillis()), 10).second;
IntervalStatistics intervalStatistics = new IntervalStatistics(trackPoints, Distance.of(1000));
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(1000), Distance.of(0));
intervalStatistics.addTrackPoints(trackPoints);
IntervalStatistics.Interval lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1);
// when
@@ -114,7 +114,8 @@ public class IntervalStatisticsTest {
}
private void whenAndThen(List<TrackPoint> trackPoints, TrackStatistics trackStatistics, float distanceInterval) {
IntervalStatistics intervalStatistics = new IntervalStatistics(trackPoints, Distance.of(distanceInterval), Distance.of(0));
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(distanceInterval), Distance.of(0));
intervalStatistics.addTrackPoints(trackPoints);
List<IntervalStatistics.Interval> intervalList = intervalStatistics.getIntervalList();
Distance totalDistance = Distance.of(0);
float totalTime = 0L;
@@ -289,7 +289,7 @@ public class TrackRecordedActivity extends AbstractTrackDeleteActivity implement
case 0:
return StatisticsRecordedFragment.newInstance(trackId);
case 1:
return IntervalsFragment.newInstance(true);
return IntervalsFragment.newInstance(trackId, true);
case 2:
return ChartFragment.newInstance(false);
case 3:
@@ -360,7 +360,7 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
case 0:
return StatisticsRecordingFragment.newInstance();
case 1:
return IntervalsFragment.newInstance(false);
return IntervalsFragment.newInstance(trackId, false);
case 2:
return ChartFragment.newInstance(false);
case 3:
@@ -72,10 +72,6 @@ public class IntervalStatisticsAdapter extends RecyclerView.Adapter<RecyclerView
}
public List<IntervalStatistics.Interval> swapData(List<IntervalStatistics.Interval> data, boolean metricUnits, boolean isReportSpeed) {
if (intervalList == data && this.metricUnits == metricUnits && this.isReportSpeed == isReportSpeed) {
return null;
}
this.metricUnits = metricUnits;
this.isReportSpeed = isReportSpeed;
intervalList = data;
@@ -745,6 +745,16 @@ public class ContentProviderUtils {
return new TrackPointIterator(this, trackId, startTrackPointId);
}
public List<TrackPoint> getTrackPoints(final Track.Id trackId, final TrackPoint.Id startTrackPointId) {
List<TrackPoint> trackPoints = new ArrayList<>();
try (TrackPointIterator trackPointIterator = getTrackPointLocationIterator(trackId, startTrackPointId)) {
while (trackPointIterator.hasNext()) {
trackPoints.add(trackPointIterator.next());
}
}
return trackPoints;
}
@Deprecated
private TrackPoint findTrackPointBy(String selection, String[] selectionArgs) {
try (Cursor cursor = getTrackPointCursor(null, selection, selectionArgs, TrackPointsColumns._ID)) {
@@ -12,7 +12,6 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
@@ -20,15 +19,10 @@ import androidx.recyclerview.widget.LinearLayoutManager;
import java.util.List;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.TrackActivityDataHubInterface;
import de.dennisguse.opentracks.adapters.IntervalStatisticsAdapter;
import de.dennisguse.opentracks.content.TrackDataHub;
import de.dennisguse.opentracks.content.TrackDataListener;
import de.dennisguse.opentracks.content.data.Speed;
import de.dennisguse.opentracks.content.data.Track;
import de.dennisguse.opentracks.content.data.TrackPoint;
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
import de.dennisguse.opentracks.databinding.IntervalListViewBinding;
import de.dennisguse.opentracks.stats.TrackStatistics;
import de.dennisguse.opentracks.util.PreferencesUtils;
import de.dennisguse.opentracks.viewmodels.IntervalStatistics;
import de.dennisguse.opentracks.viewmodels.IntervalStatisticsModel;
@@ -36,31 +30,31 @@ import de.dennisguse.opentracks.viewmodels.IntervalStatisticsModel;
/**
* A fragment to display the intervals from recorded track.
*/
public class IntervalsFragment extends Fragment implements TrackDataListener {
public class IntervalsFragment extends Fragment {
private static final String TAG = IntervalsFragment.class.getSimpleName();
private static final String FROM_TOP_TO_BOTTOM_KEY = "fromTopToBottom";
private static final String TRACK_ID_KEY = "trackId";
private IntervalStatisticsModel viewModel;
protected IntervalStatisticsAdapter.StackMode stackModeListView;
private IntervalStatisticsModel.IntervalOption selectedInterval;
private Track.Id trackId;
private boolean metricUnits;
private IntervalStatisticsAdapter adapter;
private ArrayAdapter<IntervalStatisticsModel.IntervalOption> spinnerAdapter;
private SharedPreferences sharedPreferences;
private TrackDataHub trackDataHub;
private boolean isReportSpeed;
private IntervalListViewBinding viewBinding;
protected final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = (sharedPreferences, key) -> {
if (PreferencesUtils.isKey(getContext(), R.string.stats_units_key, key) || PreferencesUtils.isKey(getContext(), R.string.stats_rate_key, key)) {
metricUnits = PreferencesUtils.isMetricUnits(sharedPreferences, getContext());
uploadIntervals();
updateIntervals(PreferencesUtils.isMetricUnits(sharedPreferences, getContext()), selectedInterval);
if (spinnerAdapter != null) {
spinnerAdapter.notifyDataSetChanged();
}
@@ -70,12 +64,14 @@ public class IntervalsFragment extends Fragment implements TrackDataListener {
/**
* Creates an instance of this class.
*
* @param trackId track's id.
* @param fromTopToBottom If true then the intervals are shown from top to bottom (the first interval on top). Otherwise the intervals are shown from bottom to top.
* @return IntervalsFragment instance.
*/
public static Fragment newInstance(boolean fromTopToBottom) {
public static Fragment newInstance(Track.Id trackId, boolean fromTopToBottom) {
Bundle bundle = new Bundle();
bundle.putBoolean(FROM_TOP_TO_BOTTOM_KEY, fromTopToBottom);
bundle.putParcelable(TRACK_ID_KEY, trackId);
IntervalsFragment intervalsFragment = new IntervalsFragment();
intervalsFragment.setArguments(bundle);
return intervalsFragment;
@@ -85,6 +81,7 @@ public class IntervalsFragment extends Fragment implements TrackDataListener {
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
stackModeListView = getArguments().getBoolean(FROM_TOP_TO_BOTTOM_KEY, true) ? IntervalStatisticsAdapter.StackMode.STACK_FROM_TOP : IntervalStatisticsAdapter.StackMode.STACK_FROM_BOTTOM;
trackId = getArguments().getParcelable(TRACK_ID_KEY);
}
@Override
@@ -127,8 +124,7 @@ public class IntervalsFragment extends Fragment implements TrackDataListener {
viewBinding.spinnerIntervals.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
selectedInterval = IntervalStatisticsModel.IntervalOption.values()[i];
uploadIntervals();
updateIntervals(metricUnits, IntervalStatisticsModel.IntervalOption.values()[i]);
}
@Override
@@ -141,11 +137,15 @@ public class IntervalsFragment extends Fragment implements TrackDataListener {
public void onResume() {
super.onResume();
resumeTrackDataHub();
sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
sharedPreferenceChangeListener.onSharedPreferenceChanged(sharedPreferences, null);
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(getContext());
Track track = contentProviderUtils.getTrack(trackId);
if (track != null) {
isReportSpeed = PreferencesUtils.isReportSpeed(sharedPreferences, getContext(), track.getCategory());
}
viewModel = new ViewModelProvider(getActivity()).get(IntervalStatisticsModel.class);
loadIntervals();
}
@@ -153,8 +153,8 @@ public class IntervalsFragment extends Fragment implements TrackDataListener {
@Override
public void onPause() {
super.onPause();
pauseTrackDataHub();
sharedPreferences.unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
viewModel.onPause();
}
@Override
@@ -180,88 +180,17 @@ public class IntervalsFragment extends Fragment implements TrackDataListener {
if (viewModel == null) {
return;
}
LiveData<List<IntervalStatistics.Interval>> liveData = viewModel.getIntervalStats(metricUnits, selectedInterval);
LiveData<List<IntervalStatistics.Interval>> liveData = viewModel.getIntervalStats(trackId, metricUnits, selectedInterval);
liveData.observe(getActivity(), intervalList -> adapter.swapData(intervalList, metricUnits, isReportSpeed));
}
private synchronized void uploadIntervals() {
if (viewModel == null) {
return;
}
viewModel.upload(metricUnits, selectedInterval);
}
private synchronized void updateIntervals(boolean metricUnits, IntervalStatisticsModel.IntervalOption selectedInterval) {
boolean update = metricUnits != this.metricUnits || !selectedInterval.equals(this.selectedInterval);
this.metricUnits = metricUnits;
this.selectedInterval = selectedInterval;
/**
* Resumes the trackDataHub.
* Needs to be synchronized because trackDataHub can be accessed by multiple threads.
*/
private synchronized void resumeTrackDataHub() {
trackDataHub = ((TrackActivityDataHubInterface) getActivity()).getTrackDataHub();
trackDataHub.registerTrackDataListener(this);
}
/**
* Pauses the trackDataHub.
* Needs to be synchronized because trackDataHub can be accessed by multiple threads.
*/
private synchronized void pauseTrackDataHub() {
trackDataHub.unregisterTrackDataListener(this);
trackDataHub = null;
}
@Override
public void onTrackUpdated(Track track) {
if (isResumed()) {
getActivity().runOnUiThread(() -> {
if (isResumed()) {
// Set category.
String category = track != null ? track.getCategory() : "";
// Set rate label.
isReportSpeed = PreferencesUtils.isReportSpeed(sharedPreferences, getContext(), category);
viewBinding.intervalRate.setText(isReportSpeed ? R.string.stats_speed : R.string.stats_pace);
}
});
}
}
@Override
public void clearTrackPoints() {
if (isResumed() && viewModel != null) {
viewModel.clear();
}
}
@Override
public void onSampledInTrackPoint(@NonNull TrackPoint trackPoint, @NonNull TrackStatistics unused, Speed unused2, double unused3) {
if (isResumed() && viewModel != null) {
viewModel.add(trackPoint);
}
}
@Override
public void onSampledOutTrackPoint(@NonNull TrackPoint trackPoint, @NonNull TrackStatistics unused) {
if (isResumed() && viewModel != null) {
viewModel.add(trackPoint);
}
}
@Override
public void onNewTrackPointsDone() {
if (isResumed() && viewModel != null) {
runOnUiThread(viewModel::onNewTrackPoints);
}
}
/**
* Runs a runnable on the UI thread.
*
* @param runnable the runnable
*/
private void runOnUiThread(Runnable runnable) {
FragmentActivity fragmentActivity = getActivity();
if (fragmentActivity != null) {
fragmentActivity.runOnUiThread(runnable);
if (update && viewModel != null) {
viewModel.update(trackId, this.metricUnits, this.selectedInterval);
}
}
}
@@ -189,7 +189,8 @@ public class AnnouncementPeriodicTask implements PeriodicTask {
boolean isReportSpeed = PreferencesUtils.isReportSpeed(sharedPreferences, context, category);
Distance minGPSDistance = PreferencesUtils.getRecordingDistanceInterval(sharedPreferences, context);
IntervalStatistics intervalStatistics = new IntervalStatistics(trackPoints, Distance.one(isMetricUnits), minGPSDistance);
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.one(isMetricUnits), minGPSDistance);
intervalStatistics.addTrackPoints(trackPoints);
IntervalStatistics.Interval lastInterval = intervalStatistics.getLastInterval();
String announcement = AnnouncementUtils.getAnnouncement(context, trackStatistics, isMetricUnits, isReportSpeed, lastInterval);
@@ -14,25 +14,32 @@ import de.dennisguse.opentracks.stats.TrackStatistics;
import de.dennisguse.opentracks.stats.TrackStatisticsUpdater;
public class IntervalStatistics {
private final List<Interval> intervalList = new ArrayList<>();
private TrackStatisticsUpdater trackStatisticsUpdater = new TrackStatisticsUpdater();
private final List<Interval> intervalList;
private final Distance distanceInterval;
private final Distance minGPSDistance;
private Interval interval, lastInterval;
/**
* @param trackPoints the list of TrackPoint.
* @param distanceInterval distance of every interval.
* @param minGPSDistance the setting value for GPS distance.
*/
public IntervalStatistics(@NonNull List<TrackPoint> trackPoints, Distance distanceInterval, Distance minGPSDistance) {
intervalList.clear();
public IntervalStatistics(Distance distanceInterval, Distance minGPSDistance) {
this.distanceInterval = distanceInterval;
this.minGPSDistance = minGPSDistance;
interval = new Interval();
lastInterval = new Interval();
intervalList = new ArrayList<>();
intervalList.add(lastInterval);
}
public void addTrackPoints(@NonNull List<TrackPoint> trackPoints) {
if (trackPoints.size() == 0) {
return;
}
TrackStatisticsUpdater trackStatisticsUpdater = new TrackStatisticsUpdater();
Interval interval = new Interval();
boolean newIntervalAdded = false;
for (TrackPoint trackPoint : trackPoints) {
trackStatisticsUpdater.addTrackPoint(trackPoint, minGPSDistance);
@@ -43,17 +50,24 @@ public class IntervalStatistics {
Interval adjustedInterval = new Interval(interval);
adjustedInterval.adjust(adjustFactor);
intervalList.remove(intervalList.size() - 1);
intervalList.add(adjustedInterval);
interval = new Interval(interval.distance.minus(adjustedInterval.distance), interval.time.minus(adjustedInterval.time));
trackStatisticsUpdater = new TrackStatisticsUpdater();
trackStatisticsUpdater.addTrackPoint(trackPoint, minGPSDistance);
lastInterval = new Interval(interval);
intervalList.add(lastInterval);
newIntervalAdded = true;
}
}
if (trackStatisticsUpdater.getTrackStatistics().getTotalDistance().toM() >= 1d) {
interval.update(trackStatisticsUpdater.getTrackStatistics(), null);
intervalList.add(interval);
if (newIntervalAdded) {
lastInterval.update(trackStatisticsUpdater.getTrackStatistics(), null);
} else {
lastInterval.set(trackStatisticsUpdater.getTrackStatistics());
}
}
@@ -110,7 +124,7 @@ public class IntervalStatistics {
loss_m = i.loss_m;
}
public void adjust(double adjustFactor) {
private void adjust(double adjustFactor) {
distance = distance.multipliedBy(adjustFactor);
time = Duration.ofMillis((long) (time.toMillis() * adjustFactor));
}
@@ -131,7 +145,7 @@ public class IntervalStatistics {
return loss_m;
}
public void update(TrackStatistics trackStatistics, @Nullable TrackPoint lastTrackPoint) {
private void update(TrackStatistics trackStatistics, @Nullable TrackPoint lastTrackPoint) {
distance = distance.plus(trackStatistics.getTotalDistance());
time = time.plus(trackStatistics.getTotalTime());
gain_m = trackStatistics.hasTotalAltitudeGain() ? trackStatistics.getTotalAltitudeGain() : gain_m;
@@ -141,5 +155,12 @@ public class IntervalStatistics {
loss_m = lastTrackPoint.hasAltitudeLoss() ? loss_m - lastTrackPoint.getAltitudeLoss() : loss_m;
}
}
private void set(TrackStatistics trackStatistics) {
distance = trackStatistics.getTotalDistance();
time = trackStatistics.getTotalTime();
gain_m = trackStatistics.hasTotalAltitudeGain() ? trackStatistics.getTotalAltitudeGain() : gain_m;
loss_m = trackStatistics.hasTotalAltitudeLoss() ? trackStatistics.getTotalAltitudeLoss() : loss_m;
}
}
}
@@ -1,19 +1,27 @@
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.util.PreferencesUtils;
import de.dennisguse.opentracks.util.UnitConversions;
/**
* This model is used to load intervals for a track.
@@ -21,65 +29,95 @@ 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();
}
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);
}
}
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);
}
registerTrackPointsObserver(trackId);
return intervalsLiveData;
}
private void loadIntervalStatistics(Track.Id trackId) {
executor.execute(() -> {
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(getApplication());
List<TrackPoint> trackPoints = contentProviderUtils.getTrackPoints(trackId, lastTrackPointId);
lastTrackPointId = trackPoints.size() > 0 ? trackPoints.get(trackPoints.size() - 1).getId() : lastTrackPointId;
intervalStatistics.addTrackPoints(trackPoints);
intervalsLiveData.postValue(intervalStatistics.getIntervalList());
});
}
private void registerTrackPointsObserver(Track.Id trackId) {
handlerThread = new HandlerThread(TAG);
handlerThread.start();
handler = new Handler(handlerThread.getLooper());
trackPointsTableObserver = new ContentObserver(handler) {
@Override
public void onChange(boolean selfChange, Uri uri) {
loadIntervalStatistics(trackId);
}
};
contentResolver.registerContentObserver(TrackPointsColumns.CONTENT_URI_BY_TRACKID, false, trackPointsTableObserver);
}
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 +145,10 @@ public class IntervalStatisticsModel extends AndroidViewModel {
.multipliedBy(multiplier);
}
public boolean equals(IntervalOption intervalOption) {
return intervalOption != null && this.multiplier == intervalOption.multiplier;
}
@Override
public String toString() {
return "" + multiplier; //TODO Somehow IntervalsFragment relies on a parsable Integer.