Speedup for charts by caching aggregated sleep amounts and steps for maximum 32 days

This commit is contained in:
Andreas Shimokawa 2017-02-26 00:40:50 +01:00
parent aac9827e63
commit 8b39ef3a52
7 changed files with 62 additions and 24 deletions

View File

@ -1,5 +1,6 @@
package nodomain.freeyourgadget.gadgetbridge.activities.charts;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
@ -31,7 +32,9 @@ import java.util.Locale;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityAmounts;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.util.LimitedQueue;
public abstract class AbstractWeekChartFragment extends AbstractChartFragment {
@ -75,16 +78,15 @@ public abstract class AbstractWeekChartFragment extends AbstractChartFragment {
}
private DefaultChartsData<BarData> refreshWeekBeforeData(DBHandler db, BarChart barChart, Calendar day, GBDevice device) {
ActivityAnalysis analysis = new ActivityAnalysis();
day = (Calendar) day.clone(); // do not modify the caller's argument
day.add(Calendar.DATE, -7);
List<BarEntry> entries = new ArrayList<>();
ArrayList<String> labels = new ArrayList<String>();
for (int counter = 0; counter < 7; counter++) {
entries.add(new BarEntry(counter, getTotalForSamples(getSamplesOfDay(db, day, device))));
ActivityAmounts amounts = getActivityAmountsForDay(db, day, device);
entries.add(new BarEntry(counter, getTotalForActivityAmounts(amounts)));
labels.add(day.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.SHORT, mLocale));
day.add(Calendar.DATE, 1);
}
@ -103,10 +105,9 @@ public abstract class AbstractWeekChartFragment extends AbstractChartFragment {
return new DefaultChartsData(barData, new PreformattedXIndexLabelFormatter(labels));
}
private DayData refreshDayPie(DBHandler db, Calendar day, GBDevice device) {
int totalValue = getTotalForSamples(getSamplesOfDay(db, day, device));
ActivityAmounts amounts = getActivityAmountsForDay(db, day, device);
int totalValue = getTotalForActivityAmounts(amounts);
PieData data = new PieData();
List<PieEntry> entries = new ArrayList<>();
@ -261,12 +262,33 @@ public abstract class AbstractWeekChartFragment extends AbstractChartFragment {
}
}
private ActivityAmounts getActivityAmountsForDay(DBHandler db, Calendar day, GBDevice device) {
LimitedQueue activityAmountCache = null;
ActivityAmounts amounts = null;
Activity activity = getActivity();
if (activity != null) {
activityAmountCache = ((ChartsActivity) activity).mActivityAmountCache;
amounts = (ActivityAmounts) (activityAmountCache.lookup(day.hashCode()));
}
if (amounts == null) {
ActivityAnalysis analysis = new ActivityAnalysis();
amounts = analysis.calculateActivityAmounts(getSamplesOfDay(db, day, device));
if (activityAmountCache != null) {
activityAmountCache.add(day.hashCode(), amounts);
}
}
return amounts;
}
abstract int getGoal();
abstract int getTotalForSamples(List<? extends ActivitySample> activitySamples);
abstract int getTotalForActivityAmounts(ActivityAmounts activityAmounts);
abstract IValueFormatter getFormatter();
abstract Integer getMainColor();
}

View File

@ -34,6 +34,11 @@ class ActivityAnalysis {
break;
}
int steps = sample.getSteps();
if (steps > 0) {
amount.addSteps(sample.getSteps());
}
if (previousSample != null) {
long timeDifference = sample.getTimestamp() - previousSample.getTimestamp();
if (previousSample.getRawKind() == sample.getRawKind()) {

View File

@ -37,6 +37,7 @@ import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.LimitedQueue;
public class ChartsActivity extends AbstractGBFragmentActivity implements ChartsHost {
@ -52,6 +53,8 @@ public class ChartsActivity extends AbstractGBFragmentActivity implements Charts
private PagerTabStrip mPagerTabStrip;
private ViewPager viewPager;
LimitedQueue mActivityAmountCache = new LimitedQueue(32);
private static class ShowDurationDialog extends Dialog {
private final String mDuration;
private TextView durationLabel;

View File

@ -4,14 +4,12 @@ import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.formatter.IValueFormatter;
import com.github.mikephil.charting.utils.ViewPortHandler;
import java.util.List;
import java.util.concurrent.TimeUnit;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityAmount;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityAmounts;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
public class WeekSleepChartFragment extends AbstractWeekChartFragment {
@ -26,11 +24,9 @@ public class WeekSleepChartFragment extends AbstractWeekChartFragment {
}
@Override
int getTotalForSamples(List<? extends ActivitySample> activitySamples) {
ActivityAnalysis analysis = new ActivityAnalysis();
ActivityAmounts amounts = analysis.calculateActivityAmounts(activitySamples);
int getTotalForActivityAmounts(ActivityAmounts activityAmounts) {
long totalSeconds = 0;
for (ActivityAmount amount : amounts.getAmounts()) {
for (ActivityAmount amount : activityAmounts.getAmounts()) {
if ((amount.getActivityKind() & ActivityKind.TYPE_SLEEP) != 0) {
totalSeconds += amount.getTotalSeconds();
}

View File

@ -2,12 +2,11 @@ package nodomain.freeyourgadget.gadgetbridge.activities.charts;
import com.github.mikephil.charting.formatter.IValueFormatter;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandCoordinator;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityAmount;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityAmounts;
public class WeekStepsChartFragment extends AbstractWeekChartFragment {
@Override
@ -25,9 +24,13 @@ public class WeekStepsChartFragment extends AbstractWeekChartFragment {
}
@Override
int getTotalForSamples(List<? extends ActivitySample> activitySamples) {
ActivityAnalysis analysis = new ActivityAnalysis();
return analysis.calculateTotalSteps(activitySamples);
int getTotalForActivityAmounts(ActivityAmounts activityAmounts) {
int totalSteps = 0;
for (ActivityAmount amount : activityAmounts.getAmounts()) {
totalSteps += amount.getTotalSteps();
amount.getTotalSteps();
}
return totalSteps;
}
@Override

View File

@ -8,6 +8,7 @@ public class ActivityAmount {
private final int activityKind;
private short percent;
private long totalSeconds;
private long totalSteps;
public ActivityAmount(int activityKind) {
this.activityKind = activityKind;
@ -17,10 +18,18 @@ public class ActivityAmount {
totalSeconds += seconds;
}
public void addSteps(long steps) {
totalSteps += steps;
}
public long getTotalSeconds() {
return totalSeconds;
}
public long getTotalSteps() {
return totalSteps;
}
public int getActivityKind() {
return activityKind;
}

View File

@ -13,14 +13,14 @@ public class LimitedQueue {
this.limit = limit;
}
public void add(int id, Object obj) {
synchronized public void add(int id, Object obj) {
if (list.size() > limit - 1) {
list.removeFirst();
}
list.add(new Pair<>(id, obj));
}
public void remove(int id) {
synchronized public void remove(int id) {
for (Iterator<Pair> iter = list.iterator(); iter.hasNext(); ) {
Pair pair = iter.next();
if ((Integer) pair.first == id) {
@ -29,7 +29,7 @@ public class LimitedQueue {
}
}
public Object lookup(int id) {
synchronized public Object lookup(int id) {
for (Pair entry : list) {
if (id == (Integer) entry.first) {
return entry.second;