Remove mStartTime and mPauseTime instance variables and read those values from SharedPreferences. Fix bug where SeekBar became visible on rotation with a lap progress ratio of zero. Fix bug where mini FABs became invisible on rotation with the stopwatch started.

This commit is contained in:
Phillip Hsu 2016-09-16 00:27:29 -07:00
parent c6c0ba69a3
commit 698892419b

View File

@ -43,10 +43,6 @@ public class StopwatchFragment extends RecyclerViewFragment<
static final String KEY_PAUSE_TIME = "pause_time"; static final String KEY_PAUSE_TIME = "pause_time";
static final String KEY_CHRONOMETER_RUNNING = "chronometer_running"; static final String KEY_CHRONOMETER_RUNNING = "chronometer_running";
// TODO: See if we can remove these? Since we save prefs in the notif. service.
private long mStartTime;
private long mPauseTime;
private ObjectAnimator mProgressAnimator; private ObjectAnimator mProgressAnimator;
private SharedPreferences mPrefs; private SharedPreferences mPrefs;
private WeakReference<FloatingActionButton> mActivityFab; private WeakReference<FloatingActionButton> mActivityFab;
@ -67,8 +63,6 @@ public class StopwatchFragment extends RecyclerViewFragment<
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
mPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity()); mPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
mStartTime = mPrefs.getLong(KEY_START_TIME, 0);
mPauseTime = mPrefs.getLong(KEY_PAUSE_TIME, 0);
// TODO: Will these be kept alive after onDestroyView()? If not, we should move these to // TODO: Will these be kept alive after onDestroyView()? If not, we should move these to
// onCreateView() or any other callback that is guaranteed to be called. // onCreateView() or any other callback that is guaranteed to be called.
mStartDrawable = ContextCompat.getDrawable(getActivity(), R.drawable.ic_start_24dp); mStartDrawable = ContextCompat.getDrawable(getActivity(), R.drawable.ic_start_24dp);
@ -84,13 +78,15 @@ public class StopwatchFragment extends RecyclerViewFragment<
View view = super.onCreateView(inflater, container, savedInstanceState); View view = super.onCreateView(inflater, container, savedInstanceState);
mChronometer.setShowCentiseconds(true, true); mChronometer.setShowCentiseconds(true, true);
if (mStartTime > 0) { long startTime = getLongFromPref(KEY_START_TIME);
long base = mStartTime; long pauseTime = getLongFromPref(KEY_PAUSE_TIME);
if (mPauseTime > 0) { // If we have a nonzero startTime from a previous session, restore it as
base += SystemClock.elapsedRealtime() - mPauseTime; // the chronometer's base. Otherwise, leave the default base.
// We're not done pausing yet, so don't reset mPauseTime. if (startTime > 0) {
if (pauseTime > 0) {
startTime += SystemClock.elapsedRealtime() - pauseTime;
} }
mChronometer.setBase(base); mChronometer.setBase(startTime);
} }
if (isStopwatchRunning()) { if (isStopwatchRunning()) {
mChronometer.start(); mChronometer.start();
@ -103,7 +99,7 @@ public class StopwatchFragment extends RecyclerViewFragment<
// would have hidden the mini FABs, if not for us already setting its // would have hidden the mini FABs, if not for us already setting its
// visibility to invisible in XML. We haven't initialized the WeakReference to // visibility to invisible in XML. We haven't initialized the WeakReference to
// our Activity's FAB yet, so this call does nothing with the FAB. // our Activity's FAB yet, so this call does nothing with the FAB.
setMiniFabsVisible(isStopwatchRunning()); setMiniFabsVisible(startTime > 0);
mPrefs.registerOnSharedPreferenceChangeListener(mPrefChangeListener); mPrefs.registerOnSharedPreferenceChangeListener(mPrefChangeListener);
return view; return view;
} }
@ -152,8 +148,7 @@ public class StopwatchFragment extends RecyclerViewFragment<
super.onDestroyView(); super.onDestroyView();
// Every view that was in our tree is dereferenced for us. // Every view that was in our tree is dereferenced for us.
// The reason we can control the animator here is because members // The reason we can control the animator here is because members
// are not dereferenced here, as evidenced by mStartTime and mPauseTime // are not dereferenced here.
// retaining their values.
if (mProgressAnimator != null) { if (mProgressAnimator != null) {
mProgressAnimator.removeAllListeners(); mProgressAnimator.removeAllListeners();
} }
@ -208,9 +203,16 @@ public class StopwatchFragment extends RecyclerViewFragment<
} else { } else {
// I verified the bar was visible already without this, so we probably don't need this, // I verified the bar was visible already without this, so we probably don't need this,
// but it's just a safety measure.. // but it's just a safety measure..
// ACTUALLY NOT A SAFETY MEASURE! // ACTUALLY NOT A SAFETY MEASURE! TODO: Why was this not acceptable?
// mSeekBar.setVisibility(View.VISIBLE); // mSeekBar.setVisibility(View.VISIBLE);
ProgressBarUtils.setProgress(mSeekBar, getCurrentLapProgressRatio(currentLap, previousLap)); double ratio = getCurrentLapProgressRatio(currentLap, previousLap);
if (ratio > 0d) {
// TODO: To be consistent with the else case, we could set the visibility
// to VISIBLE if we cared.
ProgressBarUtils.setProgress(mSeekBar, ratio);
} else {
mSeekBar.setVisibility(View.INVISIBLE);
}
} }
} else { } else {
mSeekBar.setVisibility(View.INVISIBLE); mSeekBar.setVisibility(View.INVISIBLE);
@ -223,7 +225,7 @@ public class StopwatchFragment extends RecyclerViewFragment<
syncFabIconWithStopwatchState(!running/*invert the current state*/); syncFabIconWithStopwatchState(!running/*invert the current state*/);
final Intent serviceIntent = new Intent(getActivity(), StopwatchNotificationService.class); final Intent serviceIntent = new Intent(getActivity(), StopwatchNotificationService.class);
if (mStartTime == 0) { if (getLongFromPref(KEY_START_TIME) == 0) {
setMiniFabsVisible(true); setMiniFabsVisible(true);
// Handle the default action, i.e. post the notification for the first time. // Handle the default action, i.e. post the notification for the first time.
getActivity().startService(serviceIntent); getActivity().startService(serviceIntent);
@ -234,7 +236,7 @@ public class StopwatchFragment extends RecyclerViewFragment<
@Override @Override
public void onPageSelected() { public void onPageSelected() {
setMiniFabsVisible(mStartTime > 0); setMiniFabsVisible(getLongFromPref(KEY_START_TIME) > 0);
syncFabIconWithStopwatchState(isStopwatchRunning()); syncFabIconWithStopwatchState(isStopwatchRunning());
} }
@ -332,6 +334,7 @@ public class StopwatchFragment extends RecyclerViewFragment<
private long remainingTimeBetweenLaps(Lap currentLap, Lap previousLap) { private long remainingTimeBetweenLaps(Lap currentLap, Lap previousLap) {
if (currentLap == null || previousLap == null) if (currentLap == null || previousLap == null)
return 0; return 0;
// TODO: Should we check if the subtraction results in negative number, and return 0?
return previousLap.elapsed() - currentLap.elapsed(); return previousLap.elapsed() - currentLap.elapsed();
} }
@ -343,6 +346,10 @@ public class StopwatchFragment extends RecyclerViewFragment<
return mChronometer.isRunning() || mPrefs.getBoolean(KEY_CHRONOMETER_RUNNING, false); return mChronometer.isRunning() || mPrefs.getBoolean(KEY_CHRONOMETER_RUNNING, false);
} }
private long getLongFromPref(String key) {
return mPrefs.getLong(key, 0);
}
private final OnSharedPreferenceChangeListener mPrefChangeListener = new OnSharedPreferenceChangeListener() { private final OnSharedPreferenceChangeListener mPrefChangeListener = new OnSharedPreferenceChangeListener() {
@Override @Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {