# flag bitmaps are getting cached (no more stuttering)

This commit is contained in:
Lukas Niemeier
2013-11-15 16:30:03 +01:00
parent c576830b69
commit cd7aedd02d
6 changed files with 153 additions and 90 deletions
@@ -140,7 +140,7 @@ public class GateStartRacingProcedureImpl extends BaseRacingProcedure implements
gateShutdownTime);
} else {
return new FlagPoleState(
Arrays.asList(new FlagPole(Flags.CLASS, Flags.GOLF, false)));
Arrays.asList(new FlagPole(Flags.GOLF, false)));
}
}
@@ -3,7 +3,6 @@ package com.sap.sailing.racecommittee.app.ui.fragments.raceinfo;
import java.util.List;
import android.app.Activity;
import android.util.Pair;
import android.widget.TextView;
import com.sap.sailing.domain.common.TimePoint;
@@ -19,15 +18,36 @@ import com.sap.sailing.racecommittee.app.ui.fragments.RaceFragment;
import com.sap.sailing.racecommittee.app.utils.TimeUtils;
public abstract class BaseRaceInfoRaceFragment<ProcedureType extends RacingProcedure> extends RaceFragment {
private class FlagPoleCache {
public final FlagPole flagPole;
public final TimePoint timePoint;
public final boolean hasNextFlag;
public FlagPoleCache() {
this(null, null, false);
}
public FlagPoleCache(FlagPole flagPole, TimePoint timePoint) {
this(flagPole, timePoint, true);
}
private FlagPoleCache(FlagPole flagPole, TimePoint timePoint, boolean hasNextFlag) {
this.flagPole = flagPole;
this.timePoint = timePoint;
this.hasNextFlag = hasNextFlag;
}
}
private FlagPoleCache flagPoleCache;
private final ProcedureChangedListener procedureListener;
private Pair<FlagPole, TimePoint> cachedNextFlag;
protected RaceInfoListener infoListener;
public BaseRaceInfoRaceFragment() {
this.procedureListener = new ProcedureChangedListener();
this.flagPoleCache = null;
}
@Override
@@ -65,8 +85,8 @@ public abstract class BaseRaceInfoRaceFragment<ProcedureType extends RacingProce
protected boolean updateFlagChangesCountdown(TextView targetView) {
if (cachedNextFlag == null) {
ExLog.i(BaseRaceInfoRaceFragment.class.getName(), "Refilling next-flag cache.");
if (flagPoleCache == null) {
ExLog.i(BaseRaceInfoRaceFragment.class.getSimpleName(), "Refilling next-flag cache.");
TimePoint now = MillisecondsTimePoint.now();
TimePoint startTime = getRaceState().getStartTime();
FlagPoleState flagState = getRaceState().getRacingProcedure().getActiveFlags(startTime, now);
@@ -76,17 +96,20 @@ public abstract class BaseRaceInfoRaceFragment<ProcedureType extends RacingProce
FlagPole changePole = getMostInterestingFlagPole(flagChanges);
renderFlagChangesCountdown(targetView, changeAt, changePole);
cachedNextFlag = new Pair<FlagPole, TimePoint>(changePole, changeAt);
flagPoleCache = new FlagPoleCache(changePole, changeAt);
return true;
} else {
flagPoleCache = new FlagPoleCache();
}
return false;
} else {
TimePoint changeAt = cachedNextFlag.second;
FlagPole changePole = cachedNextFlag.first;
} else if(flagPoleCache.hasNextFlag) {
TimePoint changeAt = flagPoleCache.timePoint;
FlagPole changePole = flagPoleCache.flagPole;
renderFlagChangesCountdown(targetView, changeAt, changePole);
return true;
}
return false;
}
private FlagPole getMostInterestingFlagPole(List<FlagPole> poles) {
@@ -115,7 +138,7 @@ public abstract class BaseRaceInfoRaceFragment<ProcedureType extends RacingProce
@Override
public void onActiveFlagsChanged(RacingProcedure racingProcedure) {
setupUi();
cachedNextFlag = null;
flagPoleCache = null;
}
}
}
@@ -18,7 +18,7 @@ import com.sap.sailing.racecommittee.app.ui.fragments.dialogs.AbortTypeSelection
import com.sap.sailing.racecommittee.app.ui.fragments.dialogs.RaceDialogFragment;
import com.sap.sailing.racecommittee.app.ui.fragments.dialogs.RaceFinishingTimeDialog;
import com.sap.sailing.racecommittee.app.ui.fragments.raceinfo.BaseRaceInfoRaceFragment;
import com.sap.sailing.racecommittee.app.ui.fragments.raceinfo.FlagPoleStateRenderer;
import com.sap.sailing.racecommittee.app.utils.FlagPoleStateRenderer;
import com.sap.sailing.racecommittee.app.utils.TimeUtils;
public abstract class BaseRunningRaceFragment<ProcedureType extends RacingProcedure> extends BaseRaceInfoRaceFragment<ProcedureType> {
@@ -20,7 +20,7 @@ import com.sap.sailing.racecommittee.app.R;
import com.sap.sailing.racecommittee.app.ui.fragments.dialogs.AbortModeSelectionDialog;
import com.sap.sailing.racecommittee.app.ui.fragments.dialogs.RaceDialogFragment;
import com.sap.sailing.racecommittee.app.ui.fragments.raceinfo.BaseRaceInfoRaceFragment;
import com.sap.sailing.racecommittee.app.ui.fragments.raceinfo.FlagPoleStateRenderer;
import com.sap.sailing.racecommittee.app.utils.FlagPoleStateRenderer;
import com.sap.sailing.racecommittee.app.utils.TimeUtils;
public abstract class BaseStartphaseRaceFragment<ProcedureType extends RacingProcedure> extends BaseRaceInfoRaceFragment<ProcedureType> {
@@ -1,8 +1,6 @@
package com.sap.sailing.racecommittee.app.ui.fragments.raceinfo;
package com.sap.sailing.racecommittee.app.utils;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.view.View;
import android.view.View.OnClickListener;
@@ -14,7 +12,6 @@ import com.sap.sailing.domain.common.impl.Util.Triple;
import com.sap.sailing.domain.common.racelog.FlagPole;
import com.sap.sailing.domain.common.racelog.Flags;
import com.sap.sailing.domain.racelog.state.racingprocedure.FlagPoleState;
import com.sap.sailing.racecommittee.app.R;
import com.sap.sailing.racecommittee.app.domain.ManagedRace;
import com.sap.sailing.racecommittee.app.logging.ExLog;
@@ -25,6 +22,7 @@ public class FlagPoleStateRenderer {
private final LinearLayout displayedFlagsViewGroup;
private final LinearLayout removedFlagsViewGroup;
private final FlagsBitmapCache bitmapCache;
private FlagPoleState previousState;
public FlagPoleStateRenderer(Context context, ManagedRace race,
@@ -33,6 +31,8 @@ public class FlagPoleStateRenderer {
this.race = race;
this.displayedFlagsViewGroup = upperFlagsViewGroup;
this.removedFlagsViewGroup = lowerFlagsViewGroup;
this.bitmapCache = new FlagsBitmapCache(context);
this.previousState = null;
}
@@ -40,7 +40,7 @@ public class FlagPoleStateRenderer {
if (previousState != null && FlagPoleState.describesSameState(previousState, state)) {
return;
}
ExLog.i(FlagPoleStateRenderer.class.getSimpleName(), "Rendering flags.");
ExLog.i(FlagPoleStateRenderer.class.getSimpleName(), "Re-Rendering flags.");
previousState = state;
displayedFlagsViewGroup.removeAllViews();
@@ -61,11 +61,11 @@ public class FlagPoleStateRenderer {
ImageView flagView = new ImageView(context);
flagView.setLayoutParams(layout);
flagView.setImageBitmap(getFlagBitmap(upperFlag));
flagView.setImageBitmap(bitmapCache.getBitmap(upperFlag, lowerFlag));
flagView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(v.getContext(), upperFlag.toString(), Toast.LENGTH_SHORT).show();
Toast.makeText(v.getContext(), upperFlag.toString() + "|" + lowerFlag.toString(), Toast.LENGTH_SHORT).show();
}
});
if (upperFlag == Flags.CLASS) {
@@ -75,76 +75,6 @@ public class FlagPoleStateRenderer {
return flagView;
}
private Bitmap getFlagBitmap(Flags flag) {
int resourceId = 0;
switch (flag) {
case CLASS:
resourceId = R.drawable.generic_class;
break;
case ALPHA:
resourceId = R.drawable.alpha_flag;
break;
case AP:
resourceId = R.drawable.ap_flag_mini;
break;
case BLACK:
resourceId = R.drawable.black_flag_mini;
break;
case BLUE:
resourceId = R.drawable.blue_flag_mini;
break;
case BRAVO:
resourceId = R.drawable.bravo_mini;
break;
case ESSONE:
resourceId = R.drawable.one_min_flag;
break;
case ESSTHREE:
resourceId = R.drawable.three_min_flag;
break;
case ESSTWO:
resourceId = R.drawable.two_min_flag;
break;
case FIRSTSUBSTITUTE:
resourceId = R.drawable.first_substitute_flag;
break;
case FOXTROTT:
resourceId = R.drawable.foxtrott_flag;
break;
case GOLF:
resourceId = R.drawable.golf_flag;
break;
case HOTEL:
resourceId = R.drawable.hotel_flag;
break;
case INDIA:
resourceId = R.drawable.india_flag_mini;
break;
case JURY:
resourceId = R.drawable.jury_flag_mini;
break;
case NONE:
resourceId = R.drawable.jury_flag_mini;
break;
case NOVEMBER:
resourceId = R.drawable.november_flag;
break;
case PAPA:
resourceId = R.drawable.papa_flag_mini;
break;
case XRAY:
resourceId = R.drawable.xray_flag;
break;
case ZULU:
resourceId = R.drawable.zulu_flag_mini;
break;
default:
resourceId = R.drawable.india_flag_mini;
break;
}
return BitmapFactory.decodeResource(context.getResources(), resourceId);
}
private int getFleetColorId() {
Triple<Integer, Integer, Integer> rgb = race.getFleet().getColor().getAsRGB();
return Color.rgb(rgb.getA(), rgb.getB(), rgb.getC());
@@ -0,0 +1,110 @@
package com.sap.sailing.racecommittee.app.utils;
import java.util.HashMap;
import java.util.Map;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Pair;
import com.sap.sailing.domain.common.racelog.Flags;
import com.sap.sailing.racecommittee.app.R;
import com.sap.sailing.racecommittee.app.logging.ExLog;
public class FlagsBitmapCache {
private static final Map<Pair<Flags, Flags>, Bitmap> bitmapCache = new HashMap<Pair<Flags,Flags>, Bitmap>();
private final Context context;
public FlagsBitmapCache(Context context) {
this.context = context;
}
public void clearCache() {
bitmapCache.clear();
}
public Bitmap getBitmap(Flags upperFlag, Flags lowerFlag) {
Pair<Flags, Flags> query = new Pair<Flags, Flags>(upperFlag, lowerFlag);
Bitmap flagBitmap = bitmapCache.get(query);
if (flagBitmap == null) {
ExLog.i(FlagsBitmapCache.class.getSimpleName(),
String.format("Creating Bitmap for %s|%s flag.", upperFlag, lowerFlag));
flagBitmap = createFlagBitmap(upperFlag, lowerFlag);
bitmapCache.put(query, flagBitmap);
}
return flagBitmap;
}
private Bitmap createFlagBitmap(Flags flag, Flags lowerFlag) {
int resourceId = 0;
switch (flag) {
case CLASS:
resourceId = R.drawable.generic_class;
break;
case ALPHA:
resourceId = R.drawable.alpha_flag;
break;
case AP:
resourceId = R.drawable.ap_flag;
break;
case BLACK:
resourceId = R.drawable.black_flag_mini;
break;
case BLUE:
resourceId = R.drawable.blue_flag_mini;
break;
case BRAVO:
resourceId = R.drawable.bravo_mini;
break;
case ESSONE:
resourceId = R.drawable.one_min_flag;
break;
case ESSTHREE:
resourceId = R.drawable.three_min_flag;
break;
case ESSTWO:
resourceId = R.drawable.two_min_flag;
break;
case FIRSTSUBSTITUTE:
resourceId = R.drawable.first_substitute_flag;
break;
case FOXTROTT:
resourceId = R.drawable.foxtrott_flag;
break;
case GOLF:
resourceId = R.drawable.golf_flag;
break;
case HOTEL:
resourceId = R.drawable.hotel_flag;
break;
case INDIA:
resourceId = R.drawable.india_flag_mini;
break;
case JURY:
resourceId = R.drawable.jury_flag_mini;
break;
case NONE:
resourceId = R.drawable.jury_flag_mini;
break;
case NOVEMBER:
resourceId = R.drawable.november_flag;
break;
case PAPA:
resourceId = R.drawable.papa_flag_mini;
break;
case XRAY:
resourceId = R.drawable.xray_flag;
break;
case ZULU:
resourceId = R.drawable.zulu_flag_mini;
break;
default:
resourceId = R.drawable.india_flag_mini;
break;
}
return BitmapFactory.decodeResource(context.getResources(), resourceId);
}
}