Extract DashboardData to standalone class

This commit is contained in:
José Rebelo 2024-09-28 14:24:57 +01:00
parent 7b3f7b5334
commit f5f6cb763e
22 changed files with 239 additions and 229 deletions

View File

@ -47,18 +47,10 @@ import com.google.android.material.card.MaterialCardView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
@ -78,9 +70,8 @@ import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.DashboardTodayW
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.DashboardVO2MaxCyclingWidget;
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.DashboardVO2MaxAnyWidget;
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.DashboardVO2MaxRunningWidget;
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.data.DashboardData;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.util.DashboardUtils;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
@ -164,7 +155,7 @@ public class DashboardFragment extends Fragment implements MenuProvider {
if (savedInstanceState != null && savedInstanceState.containsKey("dashboard_data") && dashboardData.isEmpty()) {
dashboardData = (DashboardData) savedInstanceState.getSerializable("dashboard_data");
} else if (dashboardData.isEmpty()) {
reloadPreferences();
dashboardData.reloadPreferences(day);
}
IntentFilter filterLocal = new IntentFilter();
@ -231,19 +222,10 @@ public class DashboardFragment extends Fragment implements MenuProvider {
day.set(Calendar.MINUTE, 59);
day.set(Calendar.SECOND, 59);
dashboardData.clear();
reloadPreferences();
dashboardData.reloadPreferences(day);
draw();
}
private void reloadPreferences() {
Prefs prefs = GBApplication.getPrefs();
dashboardData.showAllDevices = prefs.getBoolean("dashboard_devices_all", true);
dashboardData.showDeviceList = prefs.getStringSet("dashboard_devices_multiselect", new HashSet<>());
dashboardData.hrIntervalSecs = prefs.getInt("dashboard_widget_today_hr_interval", 1) * 60;
dashboardData.timeTo = (int) (day.getTimeInMillis() / 1000);
dashboardData.timeFrom = DateTimeUtils.shiftDays(dashboardData.timeTo, -1);
}
private void draw() {
Prefs prefs = GBApplication.getPrefs();
String defaultWidgetsOrder = String.join(",", getResources().getStringArray(R.array.pref_dashboard_widgets_order_default));
@ -356,135 +338,4 @@ public class DashboardFragment extends Fragment implements MenuProvider {
gridLayout.addView(fragment);
}
}
/**
* This class serves as a data collection object for all data points used by the various
* dashboard widgets. Since retrieving this data can be costly, this class makes sure it will
* only be done once. It will be passed to every widget, making sure they have the necessary
* data available.
*/
public static class DashboardData implements Serializable {
public boolean showAllDevices;
public Set<String> showDeviceList;
public int hrIntervalSecs;
public int timeFrom;
public int timeTo;
public final List<GeneralizedActivity> generalizedActivities = Collections.synchronizedList(new ArrayList<>());
private int stepsTotal;
private float stepsGoalFactor;
private long sleepTotalMinutes;
private float sleepGoalFactor;
private float distanceTotalMeters;
private float distanceGoalFactor;
private long activeMinutesTotal;
private float activeMinutesGoalFactor;
private final Map<String, Serializable> genericData = new ConcurrentHashMap<>();
public void clear() {
stepsTotal = 0;
stepsGoalFactor = 0;
sleepTotalMinutes = 0;
sleepGoalFactor = 0;
distanceTotalMeters = 0;
distanceGoalFactor = 0;
activeMinutesTotal = 0;
activeMinutesGoalFactor = 0;
generalizedActivities.clear();
genericData.clear();
}
public boolean isEmpty() {
return (stepsTotal == 0 &&
stepsGoalFactor == 0 &&
sleepTotalMinutes == 0 &&
sleepGoalFactor == 0 &&
distanceTotalMeters == 0 &&
distanceGoalFactor == 0 &&
activeMinutesTotal == 0 &&
activeMinutesGoalFactor == 0 &&
genericData.isEmpty() &&
generalizedActivities.isEmpty());
}
public synchronized int getStepsTotal() {
if (stepsTotal == 0)
stepsTotal = DashboardUtils.getStepsTotal(this);
return stepsTotal;
}
public synchronized float getStepsGoalFactor() {
if (stepsGoalFactor == 0)
stepsGoalFactor = DashboardUtils.getStepsGoalFactor(this);
return stepsGoalFactor;
}
public synchronized float getDistanceTotal() {
if (distanceTotalMeters == 0)
distanceTotalMeters = DashboardUtils.getDistanceTotal(this);
return distanceTotalMeters;
}
public synchronized float getDistanceGoalFactor() {
if (distanceGoalFactor == 0)
distanceGoalFactor = DashboardUtils.getDistanceGoalFactor(this);
return distanceGoalFactor;
}
public synchronized long getActiveMinutesTotal() {
if (activeMinutesTotal == 0)
activeMinutesTotal = DashboardUtils.getActiveMinutesTotal(this);
return activeMinutesTotal;
}
public synchronized float getActiveMinutesGoalFactor() {
if (activeMinutesGoalFactor == 0)
activeMinutesGoalFactor = DashboardUtils.getActiveMinutesGoalFactor(this);
return activeMinutesGoalFactor;
}
public synchronized long getSleepMinutesTotal() {
if (sleepTotalMinutes == 0)
sleepTotalMinutes = DashboardUtils.getSleepMinutesTotal(this);
return sleepTotalMinutes;
}
public synchronized float getSleepMinutesGoalFactor() {
if (sleepGoalFactor == 0)
sleepGoalFactor = DashboardUtils.getSleepMinutesGoalFactor(this);
return sleepGoalFactor;
}
public void put(final String key, final Serializable value) {
genericData.put(key, value);
}
public Serializable get(final String key) {
return genericData.get(key);
}
/**
* @noinspection UnusedReturnValue
*/
public Serializable computeIfAbsent(final String key, final Supplier<Serializable> supplier) {
return genericData.computeIfAbsent(key, absent -> supplier.get());
}
public static class GeneralizedActivity implements Serializable {
public ActivityKind activityKind;
public long timeFrom;
public long timeTo;
public GeneralizedActivity(ActivityKind activityKind, long timeFrom, long timeTo) {
this.activityKind = activityKind;
this.timeFrom = timeFrom;
this.timeTo = timeTo;
}
@NonNull
@Override
public String toString() {
return "Generalized activity: timeFrom=" + timeFrom + ", timeTo=" + timeTo + ", activityKind=" + activityKind + ", calculated duration: " + (timeTo - timeFrom) + " seconds";
}
}
}
}

View File

@ -11,7 +11,7 @@ import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.DashboardFragment;
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.data.DashboardData;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.devices.Vo2MaxSampleProvider;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
@ -25,7 +25,7 @@ public abstract class AbstractDashboardVO2MaxWidget extends AbstractGaugeWidget
}
@Override
protected void populateData(final DashboardFragment.DashboardData dashboardData) {
protected void populateData(final DashboardData dashboardData) {
final List<GBDevice> devices = getSupportedDevices(dashboardData);
final VO2MaxData data = new VO2MaxData();
@ -82,7 +82,7 @@ public abstract class AbstractDashboardVO2MaxWidget extends AbstractGaugeWidget
}
@Override
protected void draw(final DashboardFragment.DashboardData dashboardData) {
protected void draw(final DashboardData dashboardData) {
final VO2MaxData vo2MaxData = (VO2MaxData) dashboardData.get(getWidgetKey());
if (vo2MaxData == null) {
drawSimpleGauge(0, -1);

View File

@ -37,8 +37,8 @@ import java.util.stream.Collectors;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.DashboardFragment;
import nodomain.freeyourgadget.gadgetbridge.activities.charts.ActivityChartsActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.data.DashboardData;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
@ -47,7 +47,7 @@ public abstract class AbstractDashboardWidget extends Fragment {
protected static String ARG_DASHBOARD_DATA = "dashboard_widget_argument_data";
protected DashboardFragment.DashboardData dashboardData;
protected DashboardData dashboardData;
protected @ColorInt int color_unknown = Color.argb(25, 128, 128, 128);
protected @ColorInt int color_not_worn = Color.BLACK;
@ -65,7 +65,7 @@ public abstract class AbstractDashboardWidget extends Fragment {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
dashboardData = (DashboardFragment.DashboardData) getArguments().getSerializable(ARG_DASHBOARD_DATA);
dashboardData = (DashboardData) getArguments().getSerializable(ARG_DASHBOARD_DATA);
}
}
@ -79,7 +79,7 @@ public abstract class AbstractDashboardWidget extends Fragment {
return device.getDeviceCoordinator().supportsActivityTracking();
}
protected List<GBDevice> getSupportedDevices(final DashboardFragment.DashboardData dashboardData) {
protected List<GBDevice> getSupportedDevices(final DashboardData dashboardData) {
return GBApplication.app().getDeviceManager().getDevices()
.stream()
.filter(dev -> dashboardData.showAllDevices || dashboardData.showDeviceList.contains(dev.getAddress()))
@ -101,7 +101,7 @@ public abstract class AbstractDashboardWidget extends Fragment {
});
}
protected void chooseDevice(final DashboardFragment.DashboardData dashboardData,
protected void chooseDevice(final DashboardData dashboardData,
final Consumer<GBDevice> consumer) {
final List<GBDevice> devices = getSupportedDevices(dashboardData);

View File

@ -31,7 +31,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.DashboardFragment;
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.data.DashboardData;
public abstract class AbstractGaugeWidget extends AbstractDashboardWidget {
private static final Logger LOG = LoggerFactory.getLogger(AbstractGaugeWidget.class);
@ -84,19 +84,19 @@ public abstract class AbstractGaugeWidget extends AbstractDashboardWidget {
/**
* This is called from the async task, outside of the UI thread. It's expected that
* {@link nodomain.freeyourgadget.gadgetbridge.activities.DashboardFragment.DashboardData} be
* {@link DashboardData} be
* populated with the necessary data for display.
*
* @param dashboardData the DashboardData to populate
*/
protected abstract void populateData(DashboardFragment.DashboardData dashboardData);
protected abstract void populateData(DashboardData dashboardData);
/**
* This is called from the UI thread.
*
* @param dashboardData populated DashboardData
*/
protected abstract void draw(DashboardFragment.DashboardData dashboardData);
protected abstract void draw(DashboardData dashboardData);
private class FillDataAsyncTask extends AsyncTask<Void, Void, Void> {
@Override

View File

@ -21,7 +21,7 @@ import android.os.Bundle;
import java.util.Locale;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.DashboardFragment;
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.data.DashboardData;
/**
* A simple {@link AbstractDashboardWidget} subclass.
@ -40,7 +40,7 @@ public class DashboardActiveTimeWidget extends AbstractGaugeWidget {
* @param dashboardData An instance of DashboardFragment.DashboardData.
* @return A new instance of fragment DashboardActiveTimeWidget.
*/
public static DashboardActiveTimeWidget newInstance(final DashboardFragment.DashboardData dashboardData) {
public static DashboardActiveTimeWidget newInstance(final DashboardData dashboardData) {
final DashboardActiveTimeWidget fragment = new DashboardActiveTimeWidget();
final Bundle args = new Bundle();
args.putSerializable(ARG_DASHBOARD_DATA, dashboardData);
@ -49,13 +49,13 @@ public class DashboardActiveTimeWidget extends AbstractGaugeWidget {
}
@Override
protected void populateData(final DashboardFragment.DashboardData dashboardData) {
protected void populateData(final DashboardData dashboardData) {
dashboardData.getActiveMinutesTotal();
dashboardData.getActiveMinutesGoalFactor();
}
@Override
protected void draw(final DashboardFragment.DashboardData dashboardData) {
protected void draw(final DashboardData dashboardData) {
final long totalActiveMinutes = dashboardData.getActiveMinutesTotal();
final String valueText = String.format(
Locale.ROOT,

View File

@ -33,7 +33,7 @@ import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.DashboardFragment;
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.data.DashboardData;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.BodyEnergySample;
@ -45,7 +45,7 @@ public class DashboardBodyEnergyWidget extends AbstractGaugeWidget {
super(R.string.body_energy, "bodyenergy");
}
public static DashboardBodyEnergyWidget newInstance(final DashboardFragment.DashboardData dashboardData) {
public static DashboardBodyEnergyWidget newInstance(final DashboardData dashboardData) {
final DashboardBodyEnergyWidget fragment = new DashboardBodyEnergyWidget();
final Bundle args = new Bundle();
args.putSerializable(ARG_DASHBOARD_DATA, dashboardData);
@ -59,7 +59,7 @@ public class DashboardBodyEnergyWidget extends AbstractGaugeWidget {
}
@Override
protected void populateData(final DashboardFragment.DashboardData dashboardData) {
protected void populateData(final DashboardData dashboardData) {
final List<GBDevice> devices = getSupportedDevices(dashboardData);
final boolean isToday = DateUtils.isToday(dashboardData.timeTo * 1000L);
@ -124,7 +124,7 @@ public class DashboardBodyEnergyWidget extends AbstractGaugeWidget {
}
@Override
protected void draw(final DashboardFragment.DashboardData dashboardData) {
protected void draw(final DashboardData dashboardData) {
final BodyEnergyData bodyEnergyData = (BodyEnergyData) dashboardData.get("bodyenergy");
if (bodyEnergyData == null) {
drawSimpleGauge(0, -1);

View File

@ -54,7 +54,7 @@ import java.util.concurrent.ConcurrentHashMap;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.DashboardFragment;
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.data.DashboardData;
import nodomain.freeyourgadget.gadgetbridge.util.DashboardUtils;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
@ -228,7 +228,7 @@ public class DashboardCalendarActivity extends AbstractGBActivity {
protected Void doInBackground(Void... params) {
for (Calendar day : dayCells.keySet()) {
// Determine day color by the amount of the steps goal reached
DashboardFragment.DashboardData dashboardData = new DashboardFragment.DashboardData();
DashboardData dashboardData = new DashboardData();
dashboardData.showAllDevices = showAllDevices;
dashboardData.showDeviceList = showDeviceList;
dashboardData.timeTo = (int) (day.getTimeInMillis() / 1000);

View File

@ -19,7 +19,7 @@ package nodomain.freeyourgadget.gadgetbridge.activities.dashboard;
import android.os.Bundle;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.DashboardFragment;
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.data.DashboardData;
import nodomain.freeyourgadget.gadgetbridge.util.FormatUtils;
/**
@ -39,7 +39,7 @@ public class DashboardDistanceWidget extends AbstractGaugeWidget {
* @param dashboardData An instance of DashboardFragment.DashboardData.
* @return A new instance of fragment DashboardDistanceWidget.
*/
public static DashboardDistanceWidget newInstance(final DashboardFragment.DashboardData dashboardData) {
public static DashboardDistanceWidget newInstance(final DashboardData dashboardData) {
final DashboardDistanceWidget fragment = new DashboardDistanceWidget();
final Bundle args = new Bundle();
args.putSerializable(ARG_DASHBOARD_DATA, dashboardData);
@ -48,13 +48,13 @@ public class DashboardDistanceWidget extends AbstractGaugeWidget {
}
@Override
protected void populateData(final DashboardFragment.DashboardData dashboardData) {
protected void populateData(final DashboardData dashboardData) {
dashboardData.getDistanceTotal();
dashboardData.getDistanceGoalFactor();
}
@Override
protected void draw(final DashboardFragment.DashboardData dashboardData) {
protected void draw(final DashboardData dashboardData) {
setText(FormatUtils.getFormattedDistanceLabel(dashboardData.getDistanceTotal()));
drawSimpleGauge(
color_distance,

View File

@ -37,7 +37,7 @@ import org.slf4j.LoggerFactory;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.DashboardFragment;
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.data.DashboardData;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
/**
@ -61,7 +61,7 @@ public class DashboardGoalsWidget extends AbstractDashboardWidget {
* @param dashboardData An instance of DashboardFragment.DashboardData.
* @return A new instance of fragment DashboardGoalsWidget.
*/
public static DashboardGoalsWidget newInstance(DashboardFragment.DashboardData dashboardData) {
public static DashboardGoalsWidget newInstance(DashboardData dashboardData) {
DashboardGoalsWidget fragment = new DashboardGoalsWidget();
Bundle args = new Bundle();
args.putSerializable(ARG_DASHBOARD_DATA, dashboardData);

View File

@ -28,7 +28,7 @@ import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.DashboardFragment;
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.data.DashboardData;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.HrvSummarySample;
@ -40,7 +40,7 @@ public class DashboardHrvWidget extends AbstractGaugeWidget {
super(R.string.hrv, "hrvstatus");
}
public static DashboardHrvWidget newInstance(final DashboardFragment.DashboardData dashboardData) {
public static DashboardHrvWidget newInstance(final DashboardData dashboardData) {
final DashboardHrvWidget fragment = new DashboardHrvWidget();
final Bundle args = new Bundle();
args.putSerializable(ARG_DASHBOARD_DATA, dashboardData);
@ -54,7 +54,7 @@ public class DashboardHrvWidget extends AbstractGaugeWidget {
}
@Override
protected void populateData(final DashboardFragment.DashboardData dashboardData) {
protected void populateData(final DashboardData dashboardData) {
final List<GBDevice> devices = getSupportedDevices(dashboardData);
HrvSummarySample latestSummary = null;
@ -88,7 +88,7 @@ public class DashboardHrvWidget extends AbstractGaugeWidget {
}
@Override
protected void draw(final DashboardFragment.DashboardData dashboardData) {
protected void draw(final DashboardData dashboardData) {
final int[] colors = getColors();
final float[] segments = getSegments();
final HrvData hrvData = (HrvData) dashboardData.get("hrv");

View File

@ -21,7 +21,7 @@ import android.os.Bundle;
import java.util.Locale;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.DashboardFragment;
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.data.DashboardData;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
/**
@ -41,7 +41,7 @@ public class DashboardSleepWidget extends AbstractGaugeWidget {
* @param dashboardData An instance of DashboardFragment.DashboardData.
* @return A new instance of fragment DashboardSleepWidget.
*/
public static DashboardSleepWidget newInstance(final DashboardFragment.DashboardData dashboardData) {
public static DashboardSleepWidget newInstance(final DashboardData dashboardData) {
final DashboardSleepWidget fragment = new DashboardSleepWidget();
final Bundle args = new Bundle();
args.putSerializable(ARG_DASHBOARD_DATA, dashboardData);
@ -55,13 +55,13 @@ public class DashboardSleepWidget extends AbstractGaugeWidget {
}
@Override
protected void populateData(final DashboardFragment.DashboardData dashboardData) {
protected void populateData(final DashboardData dashboardData) {
dashboardData.getSleepMinutesTotal();
dashboardData.getSleepMinutesGoalFactor();
}
@Override
protected void draw(final DashboardFragment.DashboardData dashboardData) {
protected void draw(final DashboardData dashboardData) {
final long totalSleepMinutes = dashboardData.getSleepMinutesTotal();
final String valueText = String.format(
Locale.ROOT,

View File

@ -19,7 +19,7 @@ package nodomain.freeyourgadget.gadgetbridge.activities.dashboard;
import android.os.Bundle;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.DashboardFragment;
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.data.DashboardData;
/**
* A simple {@link AbstractDashboardWidget} subclass.
@ -38,7 +38,7 @@ public class DashboardStepsWidget extends AbstractGaugeWidget {
* @param dashboardData An instance of DashboardFragment.DashboardData.
* @return A new instance of fragment DashboardStepsWidget.
*/
public static DashboardStepsWidget newInstance(final DashboardFragment.DashboardData dashboardData) {
public static DashboardStepsWidget newInstance(final DashboardData dashboardData) {
final DashboardStepsWidget fragment = new DashboardStepsWidget();
final Bundle args = new Bundle();
args.putSerializable(ARG_DASHBOARD_DATA, dashboardData);
@ -47,13 +47,13 @@ public class DashboardStepsWidget extends AbstractGaugeWidget {
}
@Override
protected void populateData(final DashboardFragment.DashboardData dashboardData) {
protected void populateData(final DashboardData dashboardData) {
dashboardData.getStepsTotal();
dashboardData.getStepsGoalFactor();
}
@Override
protected void draw(final DashboardFragment.DashboardData dashboardData) {
protected void draw(final DashboardData dashboardData) {
setText(String.valueOf(dashboardData.getStepsTotal()));
drawSimpleGauge(
color_activity,

View File

@ -22,7 +22,7 @@ import androidx.core.content.ContextCompat;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.DashboardFragment;
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.data.DashboardData;
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.data.DashboardStressData;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
@ -31,7 +31,7 @@ public class DashboardStressBreakdownWidget extends AbstractGaugeWidget {
super(R.string.menuitem_stress, "stress");
}
public static DashboardStressBreakdownWidget newInstance(final DashboardFragment.DashboardData dashboardData) {
public static DashboardStressBreakdownWidget newInstance(final DashboardData dashboardData) {
final DashboardStressBreakdownWidget fragment = new DashboardStressBreakdownWidget();
final Bundle args = new Bundle();
args.putSerializable(ARG_DASHBOARD_DATA, dashboardData);
@ -45,12 +45,12 @@ public class DashboardStressBreakdownWidget extends AbstractGaugeWidget {
}
@Override
protected void populateData(final DashboardFragment.DashboardData dashboardData) {
protected void populateData(final DashboardData dashboardData) {
dashboardData.computeIfAbsent("stress", () -> DashboardStressData.compute(dashboardData));
}
@Override
protected void draw(final DashboardFragment.DashboardData dashboardData) {
protected void draw(final DashboardData dashboardData) {
final DashboardStressData stressData = (DashboardStressData) dashboardData.get("stress");
if (stressData == null) {
drawSimpleGauge(0, -1);

View File

@ -22,7 +22,7 @@ import androidx.core.content.ContextCompat;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.DashboardFragment;
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.data.DashboardData;
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.data.DashboardStressData;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
@ -31,7 +31,7 @@ public class DashboardStressSegmentedWidget extends AbstractGaugeWidget {
super(R.string.menuitem_stress, "stress");
}
public static DashboardStressSegmentedWidget newInstance(final DashboardFragment.DashboardData dashboardData) {
public static DashboardStressSegmentedWidget newInstance(final DashboardData dashboardData) {
final DashboardStressSegmentedWidget fragment = new DashboardStressSegmentedWidget();
final Bundle args = new Bundle();
args.putSerializable(ARG_DASHBOARD_DATA, dashboardData);
@ -45,12 +45,12 @@ public class DashboardStressSegmentedWidget extends AbstractGaugeWidget {
}
@Override
protected void populateData(final DashboardFragment.DashboardData dashboardData) {
protected void populateData(final DashboardData dashboardData) {
dashboardData.computeIfAbsent("stress", () -> DashboardStressData.compute(dashboardData));
}
@Override
protected void draw(final DashboardFragment.DashboardData dashboardData) {
protected void draw(final DashboardData dashboardData) {
final int[] colors = new int[]{
ContextCompat.getColor(GBApplication.getContext(), R.color.chart_stress_relaxed),
ContextCompat.getColor(GBApplication.getContext(), R.color.chart_stress_mild),

View File

@ -20,8 +20,8 @@ import android.os.Bundle;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.DashboardFragment;
import nodomain.freeyourgadget.gadgetbridge.activities.charts.StressChartFragment;
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.data.DashboardData;
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.data.DashboardStressData;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
@ -30,7 +30,7 @@ public class DashboardStressSimpleWidget extends AbstractGaugeWidget {
super(R.string.menuitem_stress, "stress");
}
public static DashboardStressSimpleWidget newInstance(final DashboardFragment.DashboardData dashboardData) {
public static DashboardStressSimpleWidget newInstance(final DashboardData dashboardData) {
final DashboardStressSimpleWidget fragment = new DashboardStressSimpleWidget();
final Bundle args = new Bundle();
args.putSerializable(ARG_DASHBOARD_DATA, dashboardData);
@ -44,12 +44,12 @@ public class DashboardStressSimpleWidget extends AbstractGaugeWidget {
}
@Override
protected void populateData(final DashboardFragment.DashboardData dashboardData) {
protected void populateData(final DashboardData dashboardData) {
dashboardData.computeIfAbsent("stress", () -> DashboardStressData.compute(dashboardData));
}
@Override
protected void draw(final DashboardFragment.DashboardData dashboardData) {
protected void draw(final DashboardData dashboardData) {
final DashboardStressData stressData = (DashboardStressData) dashboardData.get("stress");
if (stressData == null) {
drawSimpleGauge(0, -1);

View File

@ -48,9 +48,9 @@ import java.util.TreeMap;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.DashboardFragment;
import nodomain.freeyourgadget.gadgetbridge.activities.HeartRateUtils;
import nodomain.freeyourgadget.gadgetbridge.activities.charts.StepAnalysis;
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.data.DashboardData;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummary;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
@ -84,7 +84,7 @@ public class DashboardTodayWidget extends AbstractDashboardWidget {
* @param dashboardData An instance of DashboardFragment.DashboardData.
* @return A new instance of fragment DashboardTodayWidget.
*/
public static DashboardTodayWidget newInstance(DashboardFragment.DashboardData dashboardData) {
public static DashboardTodayWidget newInstance(DashboardData dashboardData) {
DashboardTodayWidget fragment = new DashboardTodayWidget();
Bundle args = new Bundle();
args.putSerializable(ARG_DASHBOARD_DATA, dashboardData);
@ -233,7 +233,7 @@ public class DashboardTodayWidget extends AbstractDashboardWidget {
long currentTime = Calendar.getInstance().getTimeInMillis() / 1000;
int startAngle = mode_24h && upsideDown24h ? 90 : 270;
synchronized (dashboardData.generalizedActivities) {
for (DashboardFragment.DashboardData.GeneralizedActivity activity : dashboardData.generalizedActivities) {
for (DashboardData.GeneralizedActivity activity : dashboardData.generalizedActivities) {
// Determine margin depending on 24h/12h mode
float margin = (mode_24h || activity.timeFrom >= midDaySecond) ? outerCircleMargin : innerCircleMargin;
// Draw inactive slices
@ -426,13 +426,13 @@ public class DashboardTodayWidget extends AbstractDashboardWidget {
}
private void createGeneralizedActivities() {
DashboardFragment.DashboardData.GeneralizedActivity previous = null;
DashboardData.GeneralizedActivity previous = null;
long midDaySecond = dashboardData.timeFrom + (12 * 60 * 60);
for (Map.Entry<Long, ActivityKind> activity : activityTimestamps.entrySet()) {
long timestamp = activity.getKey();
ActivityKind activityKind = activity.getValue();
if (previous == null || previous.activityKind != activityKind || (!mode_24h && timestamp == midDaySecond) || previous.timeTo < timestamp - 60) {
previous = new DashboardFragment.DashboardData.GeneralizedActivity(activityKind, timestamp, timestamp);
previous = new DashboardData.GeneralizedActivity(activityKind, timestamp, timestamp);
dashboardData.generalizedActivities.add(previous);
} else {
previous.timeTo = timestamp;

View File

@ -3,7 +3,7 @@ package nodomain.freeyourgadget.gadgetbridge.activities.dashboard;
import android.os.Bundle;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.DashboardFragment;
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.data.DashboardData;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.Vo2MaxSample;
@ -13,7 +13,7 @@ public class DashboardVO2MaxAnyWidget extends AbstractDashboardVO2MaxWidget {
super(R.string.menuitem_vo2_max, "vo2max");
}
public static DashboardVO2MaxAnyWidget newInstance(final DashboardFragment.DashboardData dashboardData) {
public static DashboardVO2MaxAnyWidget newInstance(final DashboardData dashboardData) {
final DashboardVO2MaxAnyWidget fragment = new DashboardVO2MaxAnyWidget();
final Bundle args = new Bundle();
args.putSerializable(ARG_DASHBOARD_DATA, dashboardData);

View File

@ -3,7 +3,7 @@ package nodomain.freeyourgadget.gadgetbridge.activities.dashboard;
import android.os.Bundle;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.DashboardFragment;
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.data.DashboardData;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.Vo2MaxSample;
@ -13,7 +13,7 @@ public class DashboardVO2MaxCyclingWidget extends AbstractDashboardVO2MaxWidget
super(R.string.vo2max_cycling, "vo2max");
}
public static DashboardVO2MaxCyclingWidget newInstance(final DashboardFragment.DashboardData dashboardData) {
public static DashboardVO2MaxCyclingWidget newInstance(final DashboardData dashboardData) {
final DashboardVO2MaxCyclingWidget fragment = new DashboardVO2MaxCyclingWidget();
final Bundle args = new Bundle();
args.putSerializable(ARG_DASHBOARD_DATA, dashboardData);

View File

@ -3,7 +3,7 @@ package nodomain.freeyourgadget.gadgetbridge.activities.dashboard;
import android.os.Bundle;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.DashboardFragment;
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.data.DashboardData;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.Vo2MaxSample;
@ -13,7 +13,7 @@ public class DashboardVO2MaxRunningWidget extends AbstractDashboardVO2MaxWidget
super(R.string.vo2max_running, "vo2max");
}
public static DashboardVO2MaxRunningWidget newInstance(final DashboardFragment.DashboardData dashboardData) {
public static DashboardVO2MaxRunningWidget newInstance(final DashboardData dashboardData) {
final DashboardVO2MaxRunningWidget fragment = new DashboardVO2MaxRunningWidget();
final Bundle args = new Bundle();
args.putSerializable(ARG_DASHBOARD_DATA, dashboardData);

View File

@ -0,0 +1,160 @@
package nodomain.freeyourgadget.gadgetbridge.activities.dashboard.data;
import androidx.annotation.NonNull;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.util.DashboardUtils;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
/**
* This class serves as a data collection object for all data points used by the various
* dashboard widgets. Since retrieving this data can be costly, this class makes sure it will
* only be done once. It will be passed to every widget, making sure they have the necessary
* data available.
*/
public class DashboardData implements Serializable {
public boolean showAllDevices;
public Set<String> showDeviceList;
public int hrIntervalSecs;
public int timeFrom;
public int timeTo;
public final List<GeneralizedActivity> generalizedActivities = Collections.synchronizedList(new ArrayList<>());
private int stepsTotal;
private float stepsGoalFactor;
private long sleepTotalMinutes;
private float sleepGoalFactor;
private float distanceTotalMeters;
private float distanceGoalFactor;
private long activeMinutesTotal;
private float activeMinutesGoalFactor;
private final Map<String, Serializable> genericData = new ConcurrentHashMap<>();
public void clear() {
stepsTotal = 0;
stepsGoalFactor = 0;
sleepTotalMinutes = 0;
sleepGoalFactor = 0;
distanceTotalMeters = 0;
distanceGoalFactor = 0;
activeMinutesTotal = 0;
activeMinutesGoalFactor = 0;
generalizedActivities.clear();
genericData.clear();
}
public void reloadPreferences(final Calendar day) {
Prefs prefs = GBApplication.getPrefs();
showAllDevices = prefs.getBoolean("dashboard_devices_all", true);
showDeviceList = prefs.getStringSet("dashboard_devices_multiselect", new HashSet<>());
hrIntervalSecs = prefs.getInt("dashboard_widget_today_hr_interval", 1) * 60;
timeTo = (int) (day.getTimeInMillis() / 1000);
timeFrom = DateTimeUtils.shiftDays(timeTo, -1);
}
public boolean isEmpty() {
return (stepsTotal == 0 &&
stepsGoalFactor == 0 &&
sleepTotalMinutes == 0 &&
sleepGoalFactor == 0 &&
distanceTotalMeters == 0 &&
distanceGoalFactor == 0 &&
activeMinutesTotal == 0 &&
activeMinutesGoalFactor == 0 &&
genericData.isEmpty() &&
generalizedActivities.isEmpty());
}
public synchronized int getStepsTotal() {
if (stepsTotal == 0)
stepsTotal = DashboardUtils.getStepsTotal(this);
return stepsTotal;
}
public synchronized float getStepsGoalFactor() {
if (stepsGoalFactor == 0)
stepsGoalFactor = DashboardUtils.getStepsGoalFactor(this);
return stepsGoalFactor;
}
public synchronized float getDistanceTotal() {
if (distanceTotalMeters == 0)
distanceTotalMeters = DashboardUtils.getDistanceTotal(this);
return distanceTotalMeters;
}
public synchronized float getDistanceGoalFactor() {
if (distanceGoalFactor == 0)
distanceGoalFactor = DashboardUtils.getDistanceGoalFactor(this);
return distanceGoalFactor;
}
public synchronized long getActiveMinutesTotal() {
if (activeMinutesTotal == 0)
activeMinutesTotal = DashboardUtils.getActiveMinutesTotal(this);
return activeMinutesTotal;
}
public synchronized float getActiveMinutesGoalFactor() {
if (activeMinutesGoalFactor == 0)
activeMinutesGoalFactor = DashboardUtils.getActiveMinutesGoalFactor(this);
return activeMinutesGoalFactor;
}
public synchronized long getSleepMinutesTotal() {
if (sleepTotalMinutes == 0)
sleepTotalMinutes = DashboardUtils.getSleepMinutesTotal(this);
return sleepTotalMinutes;
}
public synchronized float getSleepMinutesGoalFactor() {
if (sleepGoalFactor == 0)
sleepGoalFactor = DashboardUtils.getSleepMinutesGoalFactor(this);
return sleepGoalFactor;
}
public void put(final String key, final Serializable value) {
genericData.put(key, value);
}
public Serializable get(final String key) {
return genericData.get(key);
}
/**
* @noinspection UnusedReturnValue
*/
public Serializable computeIfAbsent(final String key, final Supplier<Serializable> supplier) {
return genericData.computeIfAbsent(key, absent -> supplier.get());
}
public static class GeneralizedActivity implements Serializable {
public ActivityKind activityKind;
public long timeFrom;
public long timeTo;
public GeneralizedActivity(ActivityKind activityKind, long timeFrom, long timeTo) {
this.activityKind = activityKind;
this.timeFrom = timeFrom;
this.timeTo = timeTo;
}
@NonNull
@Override
public String toString() {
return "Generalized activity: timeFrom=" + timeFrom + ", timeTo=" + timeTo + ", activityKind=" + activityKind + ", calculated duration: " + (timeTo - timeFrom) + " seconds";
}
}
}

View File

@ -23,7 +23,6 @@ import java.io.Serializable;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.activities.DashboardFragment;
import nodomain.freeyourgadget.gadgetbridge.activities.charts.StressChartFragment;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
@ -36,7 +35,7 @@ public class DashboardStressData implements Serializable {
public int[] ranges;
public int[] totalTime;
public static DashboardStressData compute(final DashboardFragment.DashboardData dashboardData) {
public static DashboardStressData compute(final DashboardData dashboardData) {
final List<GBDevice> devices = GBApplication.app().getDeviceManager().getDevices();
GBDevice stressDevice = null;

View File

@ -25,8 +25,8 @@ import java.util.GregorianCalendar;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.activities.DashboardFragment;
import nodomain.freeyourgadget.gadgetbridge.activities.charts.StepAnalysis;
import nodomain.freeyourgadget.gadgetbridge.activities.dashboard.data.DashboardData;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
@ -49,7 +49,7 @@ public class DashboardUtils {
return ds.getDailyTotalsForDevice(device, day, db)[0];
}
public static int getStepsTotal(DashboardFragment.DashboardData dashboardData) {
public static int getStepsTotal(DashboardData dashboardData) {
List<GBDevice> devices = GBApplication.app().getDeviceManager().getDevices();
int totalSteps = 0;
try (DBHandler dbHandler = GBApplication.acquireDB()) {
@ -64,7 +64,7 @@ public class DashboardUtils {
return totalSteps;
}
public static float getStepsGoalFactor(DashboardFragment.DashboardData dashboardData) {
public static float getStepsGoalFactor(DashboardData dashboardData) {
ActivityUser activityUser = new ActivityUser();
float stepsGoal = activityUser.getStepsGoal();
float goalFactor = getStepsTotal(dashboardData) / stepsGoal;
@ -80,7 +80,7 @@ public class DashboardUtils {
return ds.getDailyTotalsForDevice(device, day, db)[1];
}
public static long getSleepMinutesTotal(DashboardFragment.DashboardData dashboardData) {
public static long getSleepMinutesTotal(DashboardData dashboardData) {
List<GBDevice> devices = GBApplication.app().getDeviceManager().getDevices();
long totalSleepMinutes = 0;
try (DBHandler dbHandler = GBApplication.acquireDB()) {
@ -95,7 +95,7 @@ public class DashboardUtils {
return totalSleepMinutes;
}
public static float getSleepMinutesGoalFactor(DashboardFragment.DashboardData dashboardData) {
public static float getSleepMinutesGoalFactor(DashboardData dashboardData) {
ActivityUser activityUser = new ActivityUser();
int sleepMinutesGoal = activityUser.getSleepDurationGoal() * 60;
float goalFactor = (float) getSleepMinutesTotal(dashboardData) / sleepMinutesGoal;
@ -104,7 +104,7 @@ public class DashboardUtils {
return goalFactor;
}
public static float getDistanceTotal(DashboardFragment.DashboardData dashboardData) {
public static float getDistanceTotal(DashboardData dashboardData) {
List<GBDevice> devices = GBApplication.app().getDeviceManager().getDevices();
long totalSteps = 0;
try (DBHandler dbHandler = GBApplication.acquireDB()) {
@ -121,7 +121,7 @@ public class DashboardUtils {
return totalSteps * stepLength * 0.01f;
}
public static float getDistanceGoalFactor(DashboardFragment.DashboardData dashboardData) {
public static float getDistanceGoalFactor(DashboardData dashboardData) {
ActivityUser activityUser = new ActivityUser();
int distanceGoal = activityUser.getDistanceGoalMeters();
float goalFactor = getDistanceTotal(dashboardData) / distanceGoal;
@ -130,7 +130,7 @@ public class DashboardUtils {
return goalFactor;
}
public static long getActiveMinutesTotal(DashboardFragment.DashboardData dashboardData) {
public static long getActiveMinutesTotal(DashboardData dashboardData) {
List<GBDevice> devices = GBApplication.app().getDeviceManager().getDevices();
long totalActiveMinutes = 0;
try (DBHandler dbHandler = GBApplication.acquireDB()) {
@ -145,7 +145,7 @@ public class DashboardUtils {
return totalActiveMinutes;
}
public static float getActiveMinutesGoalFactor(DashboardFragment.DashboardData dashboardData) {
public static float getActiveMinutesGoalFactor(DashboardData dashboardData) {
ActivityUser activityUser = new ActivityUser();
int activeTimeGoal = activityUser.getActiveTimeGoalMinutes();
float goalFactor = (float) getActiveMinutesTotal(dashboardData) / activeTimeGoal;
@ -154,7 +154,7 @@ public class DashboardUtils {
return goalFactor;
}
public static long getActiveMinutes(GBDevice gbDevice, DBHandler db, DashboardFragment.DashboardData dashboardData) {
public static long getActiveMinutes(GBDevice gbDevice, DBHandler db, DashboardData dashboardData) {
ActivitySession stepSessionsSummary = new ActivitySession();
List<ActivitySession> stepSessions;
List<? extends ActivitySample> activitySamples = getAllSamples(db, gbDevice, dashboardData);
@ -172,7 +172,7 @@ public class DashboardUtils {
return duration / 1000 / 60;
}
public static List<? extends ActivitySample> getAllSamples(DBHandler db, GBDevice device, DashboardFragment.DashboardData dashboardData) {
public static List<? extends ActivitySample> getAllSamples(DBHandler db, GBDevice device, DashboardData dashboardData) {
SampleProvider<? extends ActivitySample> provider = getProvider(db, device);
return provider.getAllActivitySamples(dashboardData.timeFrom, dashboardData.timeTo);
}
@ -182,7 +182,7 @@ public class DashboardUtils {
return coordinator.getSampleProvider(device, db.getDaoSession());
}
public static List<BaseActivitySummary> getWorkoutSamples(DBHandler db, DashboardFragment.DashboardData dashboardData) {
public static List<BaseActivitySummary> getWorkoutSamples(DBHandler db, DashboardData dashboardData) {
return db.getDaoSession().getBaseActivitySummaryDao().queryBuilder().where(
BaseActivitySummaryDao.Properties.StartTime.gt(new Date(dashboardData.timeFrom * 1000L)),
BaseActivitySummaryDao.Properties.EndTime.lt(new Date(dashboardData.timeTo * 1000L))