IntervalsFragment/IntervalStatisticsModel refactoring: better performance with AndroidViewModel (it doesn't recreate the model every track point done anymore).

Also, it doesn't jump anymore. Fixes #669.
This commit is contained in:
Román Martínez
2021-04-03 16:32:53 +02:00
parent 8713eb3d0c
commit 978206dee4
7 changed files with 162 additions and 123 deletions
@@ -4,73 +4,84 @@ import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.util.PreferencesUtils;
import de.dennisguse.opentracks.util.StringUtils;
import de.dennisguse.opentracks.viewmodels.IntervalStatistics;
public class IntervalStatisticsAdapter extends ArrayAdapter<IntervalStatistics.Interval> {
public class IntervalStatisticsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<IntervalStatistics.Interval> intervalList;
private final Context context;
private final StackMode stackMode;
private final boolean metricUnits;
private final String category;
private boolean metricUnits;
private boolean isReportSpeed;
public IntervalStatisticsAdapter(Context context, List<IntervalStatistics.Interval> intervalList, String category, StackMode stackMode) {
super(context, R.layout.interval_stats_list_item, intervalList);
metricUnits = PreferencesUtils.isMetricUnits(PreferencesUtils.getSharedPreferences(context), context);
this.category = category;
public IntervalStatisticsAdapter(Context context, StackMode stackMode, boolean metricUnits, boolean isReportSpeed) {
this.metricUnits = metricUnits;
this.context = context;
this.stackMode = stackMode;
this.isReportSpeed = isReportSpeed;
}
//TODO Check preference handling! Should not be accessed in getView()
@NonNull
@Override
public View getView(int position, @Nullable View intervalView, @NonNull ViewGroup parent) {
int actualPosition = stackMode == StackMode.STACK_FROM_TOP ? position : getCount() - 1 - position;
IntervalStatistics.Interval interval = getItem(actualPosition);
ViewHolder viewHolder;
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.interval_stats_list_item, parent, false);
return new IntervalStatisticsAdapter.ViewHolder(view);
}
if (intervalView == null) {
viewHolder = new ViewHolder();
intervalView = LayoutInflater.from(getContext()).inflate(R.layout.interval_stats_list_item, parent, false);
viewHolder.distance = intervalView.findViewById(R.id.interval_item_distance);
viewHolder.rate = intervalView.findViewById(R.id.interval_item_rate);
viewHolder.gain = intervalView.findViewById(R.id.interval_item_gain);
viewHolder.loss = intervalView.findViewById(R.id.interval_item_loss);
intervalView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) intervalView.getTag();
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
int actualPosition = stackMode == StackMode.STACK_FROM_TOP ? position : getItemCount() - 1 - position;
int nextPosition = actualPosition + 1;
boolean isLast = actualPosition == getItemCount() - 1;
IntervalStatisticsAdapter.ViewHolder viewHolder = (IntervalStatisticsAdapter.ViewHolder) holder;
IntervalStatistics.Interval interval = intervalList.get(actualPosition);
viewHolder.itemView.setTag(actualPosition);
float sumDistance_m;
if (actualPosition + 1 == getCount() && actualPosition > 0) {
sumDistance_m = actualPosition * getItem(actualPosition - 1).getDistance_m() + interval.getDistance_m();
if (isLast && actualPosition > 0) {
sumDistance_m = actualPosition * intervalList.get(actualPosition - 1).getDistance_m() + interval.getDistance_m();
} else {
sumDistance_m = (actualPosition + 1) * interval.getDistance_m();
sumDistance_m = nextPosition * interval.getDistance_m();
}
viewHolder.distance.setText(StringUtils.formatDistance(getContext(), sumDistance_m, metricUnits));
viewHolder.distance.setText(StringUtils.formatDistance(context, sumDistance_m, metricUnits));
if (PreferencesUtils.isReportSpeed(PreferencesUtils.getSharedPreferences(getContext()), getContext(), category)) {
viewHolder.rate.setText(StringUtils.formatSpeed(getContext(), interval.getSpeed_ms(), metricUnits, true));
} else {
viewHolder.rate.setText(StringUtils.formatSpeed(getContext(), interval.getSpeed_ms(), metricUnits, false));
viewHolder.rate.setText(StringUtils.formatSpeed(context, interval.getSpeed_ms(), metricUnits, isReportSpeed));
viewHolder.gain.setText(StringUtils.formatDistance(context, interval.getGain_m(), metricUnits));
viewHolder.loss.setText(StringUtils.formatDistance(context, interval.getLoss_m(), metricUnits));
}
@Override
public int getItemCount() {
if (intervalList == null) {
return 0;
}
return intervalList.size();
}
public List<IntervalStatistics.Interval> swapData(List<IntervalStatistics.Interval> data, boolean metricUnits, boolean isReportSpeed) {
if (intervalList == data && this.metricUnits == metricUnits && this.isReportSpeed == isReportSpeed) {
return null;
}
viewHolder.gain.setText(StringUtils.formatDistance(getContext(), interval.getGain_m(), metricUnits));
viewHolder.loss.setText(StringUtils.formatDistance(getContext(), interval.getLoss_m(), metricUnits));
this.metricUnits = metricUnits;
this.isReportSpeed = isReportSpeed;
intervalList = data;
return intervalView;
if (data != null) {
this.notifyDataSetChanged();
}
return data;
}
/**
@@ -81,10 +92,18 @@ public class IntervalStatisticsAdapter extends ArrayAdapter<IntervalStatistics.I
STACK_FROM_TOP
}
private static class ViewHolder {
private TextView distance;
private TextView rate;
private TextView gain;
private TextView loss;
private static class ViewHolder extends RecyclerView.ViewHolder {
TextView distance;
TextView rate;
TextView gain;
TextView loss;
public ViewHolder(@NonNull View itemView) {
super(itemView);
distance = itemView.findViewById(R.id.interval_item_distance);
rate = itemView.findViewById(R.id.interval_item_rate);
gain = itemView.findViewById(R.id.interval_item_gain);
loss = itemView.findViewById(R.id.interval_item_loss);
}
}
}