Cleanup ChartFragment.

This commit is contained in:
Dennis Guse
2021-05-19 17:52:35 +02:00
parent 591597e4e8
commit e580a03115
5 changed files with 52 additions and 164 deletions
@@ -1,67 +0,0 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package de.dennisguse.opentracks.fragments;
import android.os.Looper;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import de.dennisguse.opentracks.chart.ChartView;
/**
* Tests {@link ChartFragment}.
*
* @author Youtao Liu
*/
//TODO Add tests that check ChartFragment
@RunWith(AndroidJUnit4.class)
public class ChartFragmentTest {
private static final double HOURS_PER_UNIT = 60.0;
private ChartFragment chartFragment;
@BeforeClass
public static void preSetUp() {
// Prepare looper for Android's message queue
if (Looper.myLooper() == null) Looper.prepare();
}
@AfterClass
public static void finalTearDown() {
if (Looper.myLooper() != null) Looper.myLooper().quit();
}
@Before
public void setUp() {
boolean chartByDistance = false;
chartFragment = ChartFragment.newInstance(chartByDistance);
chartFragment.setChartView(new ChartView(ApplicationProvider.getApplicationContext(), chartByDistance));
}
@Test
public void nothing() {
//TODO
}
}
@@ -26,6 +26,7 @@ import android.graphics.Paint.Style;
import android.graphics.Path; import android.graphics.Path;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.GestureDetector; import android.view.GestureDetector;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.ScaleGestureDetector; import android.view.ScaleGestureDetector;
@@ -114,7 +115,7 @@ public class ChartView extends View {
private int effectiveWidth = 0; private int effectiveWidth = 0;
private int effectiveHeight = 0; private int effectiveHeight = 0;
private final boolean chartByDistance; private boolean chartByDistance = false;
private boolean metricUnits = true; private boolean metricUnits = true;
private boolean reportSpeed = true; private boolean reportSpeed = true;
private boolean showPointer = false; private boolean showPointer = false;
@@ -189,9 +190,9 @@ public class ChartView extends View {
} }
}); });
public ChartView(Context context, final boolean chartByDistance) { public ChartView(Context context, AttributeSet attributeSet) {
super(context); super(context, attributeSet);
this.chartByDistance = chartByDistance;
int fontSizeSmall = ThemeUtils.getFontSizeSmallInPx(context); int fontSizeSmall = ThemeUtils.getFontSizeSmallInPx(context);
int fontSizeMedium = ThemeUtils.getFontSizeMediumInPx(context); int fontSizeMedium = ThemeUtils.getFontSizeMediumInPx(context);
@@ -366,6 +367,10 @@ public class ChartView extends View {
return true; return true;
} }
public void setChartByDistance(boolean chartByDistance) {
this.chartByDistance = chartByDistance;
}
public boolean getMetricUnits() { public boolean getMetricUnits() {
return metricUnits; return metricUnits;
} }
@@ -77,7 +77,7 @@ public interface TrackDataListener {
* *
* @param marker the marker * @param marker the marker
*/ */
default void onNewMarker(Marker marker) { default void onNewMarker(@NonNull Marker marker) {
} }
/** /**
@@ -21,10 +21,8 @@ import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
@@ -34,10 +32,8 @@ import java.util.List;
import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.TrackActivityDataHubInterface; import de.dennisguse.opentracks.TrackActivityDataHubInterface;
import de.dennisguse.opentracks.chart.ChartPoint; import de.dennisguse.opentracks.chart.ChartPoint;
import de.dennisguse.opentracks.chart.ChartView;
import de.dennisguse.opentracks.content.TrackDataHub; import de.dennisguse.opentracks.content.TrackDataHub;
import de.dennisguse.opentracks.content.TrackDataListener; import de.dennisguse.opentracks.content.TrackDataListener;
import de.dennisguse.opentracks.content.data.Distance;
import de.dennisguse.opentracks.content.data.Marker; import de.dennisguse.opentracks.content.data.Marker;
import de.dennisguse.opentracks.content.data.Speed; import de.dennisguse.opentracks.content.data.Speed;
import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.content.data.Track;
@@ -68,7 +64,6 @@ public class ChartFragment extends Fragment implements TrackDataListener {
} }
private SharedPreferences sharedPreferences; private SharedPreferences sharedPreferences;
private Distance recordingDistanceInterval;
private TrackDataHub trackDataHub; private TrackDataHub trackDataHub;
@@ -80,40 +75,34 @@ public class ChartFragment extends Fragment implements TrackDataListener {
private boolean chartByDistance; private boolean chartByDistance;
private ChartBinding viewBinding; private ChartBinding viewBinding;
// UI elements
private ChartView chartView;
private final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() { private final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
@Override @Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (PreferencesUtils.isKey(getContext(), R.string.stats_units_key, key)) { if (PreferencesUtils.isKey(getContext(), R.string.stats_units_key, key)) {
boolean metricUnits = PreferencesUtils.isMetricUnits(sharedPreferences, getContext()); boolean metricUnits = PreferencesUtils.isMetricUnits(sharedPreferences, getContext());
if (metricUnits != chartView.getMetricUnits()) { if (metricUnits != viewBinding.chartView.getMetricUnits()) {
chartView.setMetricUnits(metricUnits); viewBinding.chartView.setMetricUnits(metricUnits);
runOnUiThread(() -> { runOnUiThread(() -> {
if (isResumed()) { if (isResumed()) {
chartView.requestLayout(); viewBinding.chartView.requestLayout();
} }
}); });
} }
} }
if (PreferencesUtils.isKey(getContext(), R.string.stats_rate_key, key)) { if (PreferencesUtils.isKey(getContext(), R.string.stats_rate_key, key)) {
boolean reportSpeed = PreferencesUtils.isReportSpeed(sharedPreferences, getContext(), category); boolean reportSpeed = PreferencesUtils.isReportSpeed(sharedPreferences, getContext(), category);
if (reportSpeed != chartView.getReportSpeed()) { if (reportSpeed != viewBinding.chartView.getReportSpeed()) {
chartView.setReportSpeed(reportSpeed); viewBinding.chartView.setReportSpeed(reportSpeed);
chartView.applyReportSpeed(); viewBinding.chartView.applyReportSpeed();
runOnUiThread(() -> { runOnUiThread(() -> {
if (isResumed()) { if (isResumed()) {
chartView.requestLayout(); viewBinding.chartView.requestLayout();
} }
}); });
} }
} }
if (PreferencesUtils.isKey(getContext(), R.string.recording_distance_interval_key, key)) {
recordingDistanceInterval = PreferencesUtils.getRecordingDistanceInterval(sharedPreferences, getContext());
}
} }
}; };
@@ -123,12 +112,12 @@ public class ChartFragment extends Fragment implements TrackDataListener {
private final Runnable updateChart = new Runnable() { private final Runnable updateChart = new Runnable() {
@Override @Override
public void run() { public void run() {
if (!isResumed() || trackDataHub == null) { if (!isResumed()) {
return; return;
} }
chartView.setShowPointer(isSelectedTrackRecording()); viewBinding.chartView.setShowPointer(isSelectedTrackRecording());
chartView.invalidate(); viewBinding.chartView.invalidate();
} }
}; };
@@ -138,27 +127,15 @@ public class ChartFragment extends Fragment implements TrackDataListener {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
chartByDistance = getArguments().getBoolean(KEY_CHART_VIEW_BY_DISTANCE_KEY, true); chartByDistance = getArguments().getBoolean(KEY_CHART_VIEW_BY_DISTANCE_KEY, true);
recordingDistanceInterval = PreferencesUtils.getRecordingDistanceIntervalDefault(getContext());
// Create a chartView here to store data thus won't need to reload all the data on every onStart or onResume.
chartView = new ChartView(getContext(), chartByDistance);
} }
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
viewBinding = ChartBinding.inflate(inflater, container, false); viewBinding = ChartBinding.inflate(inflater, container, false);
viewBinding.chartView.setChartByDistance(chartByDistance);
return viewBinding.getRoot(); return viewBinding.getRoot();
} }
@Override
public void onStart() {
super.onStart();
LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
viewBinding.chartViewLayout.addView(chartView, layoutParams);
}
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
@@ -178,13 +155,6 @@ public class ChartFragment extends Fragment implements TrackDataListener {
sharedPreferences.unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener); sharedPreferences.unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
} }
@Override
public void onStop() {
super.onStop();
viewBinding.chartViewLayout.removeView(chartView);
}
@Override @Override
public void onDestroyView() { public void onDestroyView() {
super.onDestroyView(); super.onDestroyView();
@@ -199,78 +169,64 @@ public class ChartFragment extends Fragment implements TrackDataListener {
@Override @Override
public void onTrackUpdated(Track track) { public void onTrackUpdated(Track track) {
if (isResumed()) { if (track == null) {
if (track == null || track.getTrackStatistics() == null) { category = "";
category = ""; return;
return; }
}
category = track.getCategory(); category = track.getCategory();
boolean reportSpeed = PreferencesUtils.isReportSpeed(PreferencesUtils.getSharedPreferences(getContext()), getContext(), category); boolean reportSpeed = PreferencesUtils.isReportSpeed(PreferencesUtils.getSharedPreferences(getContext()), getContext(), category);
if (reportSpeed != chartView.getReportSpeed()) { if (reportSpeed != viewBinding.chartView.getReportSpeed()) {
chartView.setReportSpeed(reportSpeed); viewBinding.chartView.setReportSpeed(reportSpeed);
chartView.applyReportSpeed(); viewBinding.chartView.applyReportSpeed();
}
} }
} }
@Override @Override
public void clearTrackPoints() { public void clearTrackPoints() {
if (isResumed()) { pendingPoints.clear();
pendingPoints.clear(); viewBinding.chartView.reset();
chartView.reset(); runOnUiThread(() -> {
runOnUiThread(() -> { if (isResumed()) {
if (isResumed()) { viewBinding.chartView.resetScroll();
chartView.resetScroll(); }
} });
});
}
} }
public void onSampledInTrackPoint(@NonNull TrackPoint trackPoint, @NonNull TrackStatistics trackStatistics, Speed smoothedSpeed, double smoothedAltitude_m) { public void onSampledInTrackPoint(@NonNull TrackPoint trackPoint, @NonNull TrackStatistics trackStatistics, Speed smoothedSpeed, double smoothedAltitude_m) {
if (isResumed()) { ChartPoint point = new ChartPoint(trackStatistics, trackPoint, smoothedSpeed, smoothedAltitude_m, chartByDistance, viewBinding.chartView.getMetricUnits());
ChartPoint point = new ChartPoint(trackStatistics, trackPoint, smoothedSpeed, smoothedAltitude_m, chartByDistance, chartView.getMetricUnits()); pendingPoints.add(point);
pendingPoints.add(point);
}
} }
@Override @Override
public void onNewTrackPointsDone() { public void onNewTrackPointsDone() {
if (isResumed()) { viewBinding.chartView.addChartPoints(pendingPoints);
chartView.addChartPoints(pendingPoints); pendingPoints.clear();
pendingPoints.clear(); runOnUiThread(updateChart);
runOnUiThread(updateChart);
}
} }
@Override @Override
public void clearMarkers() { public void clearMarkers() {
if (isResumed()) { viewBinding.chartView.clearMarker();
chartView.clearMarker();
}
} }
@Override @Override
public void onNewMarker(Marker marker) { public void onNewMarker(@NonNull Marker marker) {
if (isResumed() && marker != null) { viewBinding.chartView.addMarker(marker);
chartView.addMarker(marker);
}
} }
@Override @Override
public void onNewMarkersDone() { public void onNewMarkersDone() {
if (isResumed()) { runOnUiThread(updateChart);
runOnUiThread(updateChart);
}
} }
/** /**
* Checks the chart settings. * Checks the chart settings.
*/ */
private void checkChartSettings() { private void checkChartSettings() {
boolean needUpdate = chartView.applyReportSpeed(); boolean needUpdate = viewBinding.chartView.applyReportSpeed();
if (needUpdate) { if (needUpdate) {
chartView.postInvalidate(); viewBinding.chartView.postInvalidate();
} }
} }
@@ -313,9 +269,4 @@ public class ChartFragment extends Fragment implements TrackDataListener {
fragmentActivity.runOnUiThread(runnable); fragmentActivity.runOnUiThread(runnable);
} }
} }
@VisibleForTesting
void setChartView(ChartView view) {
chartView = view;
}
} }
+4 -5
View File
@@ -13,9 +13,8 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
--> -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/chart_view_layout" <de.dennisguse.opentracks.chart.ChartView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/chart_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="match_parent" />
android:layout_weight="1"
android:orientation="vertical" />