Wrote potentially unnecessary stuff
This commit is contained in:
parent
e157498147
commit
d6eeac1db1
@ -0,0 +1,92 @@
|
||||
package com.philliphsu.clock2.stopwatch;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* Created by Phillip Hsu on 9/11/2016.
|
||||
*/
|
||||
public abstract class BaseStopwatchController { // TODO: Extend this for use in StopwatchFragment and StopwatchNotificationSErvice
|
||||
// TODO: EIther expose these to subclasses or write an API for them to call
|
||||
// to write to prefs.
|
||||
private static final String KEY_START_TIME = "start_time";
|
||||
private static final String KEY_PAUSE_TIME = "pause_time";
|
||||
private static final String KEY_RUNNING = "running";
|
||||
|
||||
private final AsyncLapsTableUpdateHandler mUpdateHandler;
|
||||
private final SharedPreferences mPrefs;
|
||||
|
||||
private Stopwatch mStopwatch;
|
||||
private Lap mCurrentLap;
|
||||
private Lap mPreviousLap;
|
||||
|
||||
public BaseStopwatchController(@NonNull AsyncLapsTableUpdateHandler updateHandler,
|
||||
@NonNull SharedPreferences prefs) {
|
||||
mUpdateHandler = updateHandler;
|
||||
mPrefs = prefs;
|
||||
long startTime = mPrefs.getLong(KEY_START_TIME, 0);
|
||||
long pauseTime = mPrefs.getLong(KEY_PAUSE_TIME, 0);
|
||||
mStopwatch = new Stopwatch(startTime, pauseTime);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
if (!mStopwatch.hasStarted()) {
|
||||
// addNewLap() won't call through unless chronometer is running, which
|
||||
// we can't start until we compute mStartTime
|
||||
mCurrentLap = new Lap();
|
||||
mUpdateHandler.asyncInsert(mCurrentLap);
|
||||
}
|
||||
mStopwatch.run();
|
||||
if (!mCurrentLap.isRunning()) {
|
||||
mCurrentLap.resume();
|
||||
mUpdateHandler.asyncUpdate(mCurrentLap.getId(), mCurrentLap);
|
||||
}
|
||||
savePrefs();
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
mStopwatch.pause();
|
||||
mCurrentLap.pause();
|
||||
mUpdateHandler.asyncUpdate(mCurrentLap.getId(), mCurrentLap);
|
||||
savePrefs();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
mStopwatch.stop();
|
||||
mCurrentLap = null;
|
||||
mPreviousLap = null;
|
||||
mUpdateHandler.asyncClear(); // Clear laps
|
||||
savePrefs();
|
||||
}
|
||||
|
||||
public void addNewLap(String currentLapTotalText) {
|
||||
if (mCurrentLap != null) {
|
||||
mCurrentLap.end(currentLapTotalText);
|
||||
}
|
||||
mPreviousLap = mCurrentLap;
|
||||
mCurrentLap = new Lap();
|
||||
if (mPreviousLap != null) {
|
||||
// if (getAdapter().getItemCount() == 0) {
|
||||
// mUpdateHandler.asyncInsert(mPreviousLap);
|
||||
// } else {
|
||||
mUpdateHandler.asyncUpdate(mPreviousLap.getId(), mPreviousLap);
|
||||
// }
|
||||
}
|
||||
mUpdateHandler.asyncInsert(mCurrentLap);
|
||||
}
|
||||
|
||||
public final Stopwatch getStopwatch() {
|
||||
return mStopwatch;
|
||||
}
|
||||
|
||||
public boolean isStopwatchRunning() {
|
||||
return mPrefs.getBoolean(KEY_RUNNING, false);
|
||||
}
|
||||
|
||||
private void savePrefs() {
|
||||
mPrefs.edit().putLong(KEY_START_TIME, mStopwatch.getStartTime())
|
||||
.putLong(KEY_PAUSE_TIME, mStopwatch.getPauseTime())
|
||||
.putBoolean(KEY_RUNNING, mStopwatch.isRunning())
|
||||
.apply();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
package com.philliphsu.clock2.stopwatch;
|
||||
|
||||
import android.os.SystemClock;
|
||||
|
||||
/**
|
||||
* Created by Phillip Hsu on 9/11/2016.
|
||||
*/
|
||||
public final class Stopwatch {
|
||||
private static final String TAG = "Stopwatch";
|
||||
|
||||
private long mStartTime;
|
||||
private long mPauseTime;
|
||||
|
||||
public Stopwatch(long startTime, long pauseTime) {
|
||||
mStartTime = startTime;
|
||||
mPauseTime = pauseTime;
|
||||
}
|
||||
|
||||
public synchronized void pause() {
|
||||
if (!isRunning())
|
||||
throw new IllegalStateException("This stopwatch cannot be paused because it is not running");
|
||||
if (mPauseTime > 0)
|
||||
throw new IllegalStateException("This stopwatch is already paused");
|
||||
mPauseTime = SystemClock.elapsedRealtime();
|
||||
}
|
||||
|
||||
public synchronized void run() {
|
||||
if (isRunning())
|
||||
throw new IllegalStateException("This stopwatch is already running");
|
||||
mStartTime += SystemClock.elapsedRealtime() - mPauseTime;
|
||||
mPauseTime = 0;
|
||||
}
|
||||
|
||||
public synchronized void stop() {
|
||||
mStartTime = 0;
|
||||
mPauseTime = 0;
|
||||
}
|
||||
|
||||
public long getStartTime() {
|
||||
return mStartTime;
|
||||
}
|
||||
|
||||
public long getPauseTime() {
|
||||
return mPauseTime;
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
return hasStarted() && mPauseTime == 0;
|
||||
}
|
||||
|
||||
public boolean hasStarted() {
|
||||
// Not required to be presently running to have been started
|
||||
return mStartTime > 0;
|
||||
}
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
package com.philliphsu.clock2.stopwatch;
|
||||
|
||||
/**
|
||||
* Created by Phillip Hsu on 9/11/2016.
|
||||
*/
|
||||
public final class StopwatchController {
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -6,7 +6,6 @@ import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.SystemClock;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
@ -37,22 +36,17 @@ public class StopwatchFragment extends RecyclerViewFragment<
|
||||
LapsAdapter> {
|
||||
private static final String TAG = "StopwatchFragment";
|
||||
|
||||
// Exposed for StopwatchNotificationService
|
||||
static final String KEY_START_TIME = "start_time";
|
||||
static final String KEY_PAUSE_TIME = "pause_time";
|
||||
static final String KEY_CHRONOMETER_RUNNING = "chronometer_running";
|
||||
|
||||
private long mStartTime;
|
||||
private long mPauseTime;
|
||||
private Lap mCurrentLap;
|
||||
private Lap mPreviousLap;
|
||||
|
||||
private AsyncLapsTableUpdateHandler mUpdateHandler;
|
||||
private ObjectAnimator mProgressAnimator;
|
||||
private SharedPreferences mPrefs;
|
||||
private WeakReference<FloatingActionButton> mActivityFab;
|
||||
private Drawable mStartDrawable;
|
||||
private Drawable mPauseDrawable;
|
||||
// TODO: Actual subclass
|
||||
private BaseStopwatchController mController;
|
||||
|
||||
// For read-only purposes within this Fragment.
|
||||
// Actual changes are persisted by the controller.
|
||||
private Lap mCurrentLap;
|
||||
private Lap mPreviousLap;
|
||||
|
||||
@Bind(R.id.chronometer) ChronometerWithMillis mChronometer;
|
||||
@Bind(R.id.new_lap) FloatingActionButton mNewLapButton;
|
||||
@ -67,12 +61,6 @@ public class StopwatchFragment extends RecyclerViewFragment<
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mUpdateHandler = new AsyncLapsTableUpdateHandler(getActivity(), null/*we shouldn't need a scroll handler*/);
|
||||
mPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
||||
mStartTime = mPrefs.getLong(KEY_START_TIME, 0);
|
||||
mPauseTime = mPrefs.getLong(KEY_PAUSE_TIME, 0);
|
||||
Log.d(TAG, "mStartTime = " + mStartTime
|
||||
+ ", mPauseTime = " + mPauseTime);
|
||||
// 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.
|
||||
mStartDrawable = ContextCompat.getDrawable(getActivity(), R.drawable.ic_start_24dp);
|
||||
@ -85,21 +73,13 @@ public class StopwatchFragment extends RecyclerViewFragment<
|
||||
Log.d(TAG, "onCreateView()");
|
||||
View view = super.onCreateView(inflater, container, savedInstanceState);
|
||||
|
||||
mChronometer.setShowCentiseconds(true, true);
|
||||
if (mStartTime > 0) {
|
||||
long base = mStartTime;
|
||||
if (mPauseTime > 0) {
|
||||
base += SystemClock.elapsedRealtime() - mPauseTime;
|
||||
// We're not done pausing yet, so don't reset mPauseTime.
|
||||
}
|
||||
mChronometer.setBase(base);
|
||||
}
|
||||
if (isStopwatchRunning()) {
|
||||
mChronometer.start();
|
||||
// Note: mChronometer.isRunning() will return false at this point and
|
||||
// in other upcoming lifecycle methods because it is not yet visible
|
||||
// (i.e. mVisible == false).
|
||||
}
|
||||
AsyncLapsTableUpdateHandler updateHandler = new AsyncLapsTableUpdateHandler(
|
||||
getActivity(), null/*we shouldn't need a scroll handler*/);
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
||||
// This can't be initialized until the layout is inflated, because we need the
|
||||
// mChronometer reference for the controller.
|
||||
mController = new StopwatchViewController(updateHandler, prefs, mChronometer);
|
||||
|
||||
// The primary reason we call this is to show the mini FABs after rotate,
|
||||
// if the stopwatch is running. If the stopwatch is stopped, then this
|
||||
// would have hidden the mini FABs, if not for us already setting its
|
||||
@ -158,9 +138,6 @@ public class StopwatchFragment extends RecyclerViewFragment<
|
||||
if (mProgressAnimator != null) {
|
||||
mProgressAnimator.removeAllListeners();
|
||||
}
|
||||
Log.d(TAG, "onDestroyView()");
|
||||
Log.d(TAG, "mStartTime = " + mStartTime
|
||||
+ ", mPauseTime = " + mPauseTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -203,7 +180,8 @@ public class StopwatchFragment extends RecyclerViewFragment<
|
||||
//
|
||||
// NOTE: If we just recreated ourselves due to rotation, mChronometer.isRunning() == false,
|
||||
// because it is not yet visible (i.e. mVisible == false).
|
||||
if (isStopwatchRunning()) {
|
||||
if (mController.isStopwatchRunning()) {
|
||||
// TODO: I think we should just pass in the two laps as local params
|
||||
startNewProgressBarAnimator();
|
||||
} else {
|
||||
// I verified the bar was visible already without this, so we probably don't need this,
|
||||
@ -220,10 +198,7 @@ public class StopwatchFragment extends RecyclerViewFragment<
|
||||
@Override
|
||||
public void onFabClick() {
|
||||
if (mChronometer.isRunning()) {
|
||||
mPauseTime = SystemClock.elapsedRealtime();
|
||||
mChronometer.stop();
|
||||
mCurrentLap.pause();
|
||||
mUpdateHandler.asyncUpdate(mCurrentLap.getId(), mCurrentLap);
|
||||
mController.pause();
|
||||
// No issues controlling the animator here, because onLoadFinished() can't
|
||||
// call through to startNewProgressBarAnimator(), because by that point
|
||||
// the chronometer won't be running.
|
||||
@ -234,20 +209,7 @@ public class StopwatchFragment extends RecyclerViewFragment<
|
||||
mProgressAnimator.cancel();
|
||||
}
|
||||
} else {
|
||||
if (mStartTime == 0) {
|
||||
// addNewLap() won't call through unless chronometer is running, which
|
||||
// we can't start until we compute mStartTime
|
||||
mCurrentLap = new Lap();
|
||||
mUpdateHandler.asyncInsert(mCurrentLap);
|
||||
}
|
||||
mStartTime += SystemClock.elapsedRealtime() - mPauseTime;
|
||||
mPauseTime = 0;
|
||||
mChronometer.setBase(mStartTime);
|
||||
mChronometer.start();
|
||||
if (!mCurrentLap.isRunning()) {
|
||||
mCurrentLap.resume();
|
||||
mUpdateHandler.asyncUpdate(mCurrentLap.getId(), mCurrentLap);
|
||||
}
|
||||
mController.run();
|
||||
// This animator instance will end up having end() called on it. When
|
||||
// the table update prompts us to requery, onLoadFinished will be called as a result.
|
||||
// There, it calls startNewProgressAnimator() to end this animation and starts an
|
||||
@ -257,7 +219,6 @@ public class StopwatchFragment extends RecyclerViewFragment<
|
||||
// }
|
||||
getActivity().startService(new Intent(getActivity(), StopwatchNotificationService.class));
|
||||
}
|
||||
savePrefs();
|
||||
// TOneverDO: Precede savePrefs(), or else we don't save false to KEY_CHRONOMETER_RUNNING
|
||||
/// and updateFab will update the wrong icon.
|
||||
updateAllFabs();
|
||||
@ -280,23 +241,7 @@ public class StopwatchFragment extends RecyclerViewFragment<
|
||||
|
||||
@OnClick(R.id.new_lap)
|
||||
void addNewLap() {
|
||||
if (!mChronometer.isRunning()) {
|
||||
Log.d(TAG, "Cannot add new lap");
|
||||
return;
|
||||
}
|
||||
if (mCurrentLap != null) {
|
||||
mCurrentLap.end(mChronometer.getText().toString());
|
||||
}
|
||||
mPreviousLap = mCurrentLap;
|
||||
mCurrentLap = new Lap();
|
||||
if (mPreviousLap != null) {
|
||||
// if (getAdapter().getItemCount() == 0) {
|
||||
// mUpdateHandler.asyncInsert(mPreviousLap);
|
||||
// } else {
|
||||
mUpdateHandler.asyncUpdate(mPreviousLap.getId(), mPreviousLap);
|
||||
// }
|
||||
}
|
||||
mUpdateHandler.asyncInsert(mCurrentLap);
|
||||
mController.addNewLap(mChronometer.getText().toString());
|
||||
// This would end up being called twice: here, and in onLoadFinished(), because the
|
||||
// table updates will prompt us to requery.
|
||||
// startNewProgressBarAnimator();
|
||||
@ -304,17 +249,13 @@ public class StopwatchFragment extends RecyclerViewFragment<
|
||||
|
||||
@OnClick(R.id.stop)
|
||||
void stop() {
|
||||
mChronometer.stop();
|
||||
mChronometer.setBase(SystemClock.elapsedRealtime());
|
||||
// ----------------------------------------------------------------------
|
||||
// TOneverDO: Precede these with mProgressAnimator.end(), otherwise our
|
||||
// Animator.onAnimationEnd() callback won't hide SeekBar in time.
|
||||
mStartTime = 0;
|
||||
mPauseTime = 0;
|
||||
mController.stop();
|
||||
// ----------------------------------------------------------------------
|
||||
mCurrentLap = null;
|
||||
mPreviousLap = null;
|
||||
mUpdateHandler.asyncClear(); // Clear laps
|
||||
// No issues controlling the animator here, because onLoadFinished() can't
|
||||
// call through to startNewProgressBarAnimator(), because by that point
|
||||
// the chronometer won't be running.
|
||||
@ -322,7 +263,6 @@ public class StopwatchFragment extends RecyclerViewFragment<
|
||||
mProgressAnimator.end();
|
||||
}
|
||||
mProgressAnimator = null;
|
||||
savePrefs();
|
||||
// TOneverDO: Precede savePrefs(), or else we don't save false to KEY_CHRONOMETER_RUNNING
|
||||
/// and updateFab will update the wrong icon.
|
||||
updateAllFabs();
|
||||
@ -342,14 +282,14 @@ public class StopwatchFragment extends RecyclerViewFragment<
|
||||
}
|
||||
|
||||
private void updateMiniFabs() {
|
||||
boolean started = mStartTime > 0;
|
||||
boolean started = mController.getStopwatch().hasStarted();
|
||||
int vis = started ? View.VISIBLE : View.INVISIBLE;
|
||||
mNewLapButton.setVisibility(vis);
|
||||
mStopButton.setVisibility(vis);
|
||||
}
|
||||
|
||||
private void updateFab() {
|
||||
mActivityFab.get().setImageDrawable(isStopwatchRunning() ? mPauseDrawable : mStartDrawable);
|
||||
mActivityFab.get().setImageDrawable(mController.isStopwatchRunning() ? mPauseDrawable : mStartDrawable);
|
||||
}
|
||||
|
||||
private void startNewProgressBarAnimator() {
|
||||
@ -414,21 +354,6 @@ public class StopwatchFragment extends RecyclerViewFragment<
|
||||
return mPreviousLap.elapsed() - mCurrentLap.elapsed();
|
||||
}
|
||||
|
||||
private void savePrefs() {
|
||||
mPrefs.edit().putLong(KEY_START_TIME, mStartTime)
|
||||
.putLong(KEY_PAUSE_TIME, mPauseTime)
|
||||
.putBoolean(KEY_CHRONOMETER_RUNNING, mChronometer.isRunning())
|
||||
.apply();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the state of the stopwatch when we're in a resumed and visible state,
|
||||
* or when we're going through a rotation
|
||||
*/
|
||||
private boolean isStopwatchRunning() {
|
||||
return mChronometer.isRunning() || mPrefs.getBoolean(KEY_CHRONOMETER_RUNNING, false);
|
||||
}
|
||||
|
||||
// ======================= DO NOT IMPLEMENT ============================
|
||||
|
||||
@Override
|
||||
|
||||
@ -68,10 +68,18 @@ public class StopwatchNotificationService extends ChronometerNotificationService
|
||||
@Override
|
||||
protected void handleStartPauseAction(Intent intent, int flags, long startId) {
|
||||
// TODO: Tell StopwatchFragment to start/pause itself.. perhaps with an Intent?
|
||||
boolean running = mPrefs.getBoolean(StopwatchFragment.KEY_CHRONOMETER_RUNNING, false);
|
||||
boolean running = mPrefs.getBoolean("KEY_RUNNING", false);
|
||||
syncNotificationWithStopwatchState(!running);
|
||||
SharedPreferences.Editor editor = mPrefs.edit();
|
||||
editor.putBoolean(StopwatchFragment.KEY_CHRONOMETER_RUNNING, !running);
|
||||
editor.putBoolean("KEY_RUNNING", !running);
|
||||
if (running) {
|
||||
editor.putLong("key_pause_time", SystemClock.elapsedRealtime());
|
||||
} else {
|
||||
long startTime = mPrefs.getLong("key_start_time", 0);
|
||||
long pauseTime = mPrefs.getLong("key_pause_time", 0);
|
||||
editor.putLong("key_start_time", startTime + SystemClock.elapsedRealtime() - pauseTime);
|
||||
}
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -0,0 +1,78 @@
|
||||
package com.philliphsu.clock2.stopwatch;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.SystemClock;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Created by Phillip Hsu on 9/11/2016.
|
||||
*/
|
||||
public final class StopwatchViewController extends BaseStopwatchController {
|
||||
private static final String TAG = "StopwatchViewController";
|
||||
|
||||
private final ChronometerWithMillis mChronometer;
|
||||
|
||||
public StopwatchViewController(@NonNull AsyncLapsTableUpdateHandler updateHandler,
|
||||
@NonNull SharedPreferences prefs,
|
||||
@NonNull ChronometerWithMillis chronometer) {
|
||||
super(updateHandler, prefs);
|
||||
mChronometer = chronometer;
|
||||
|
||||
mChronometer.setShowCentiseconds(true, true);
|
||||
final Stopwatch sw = getStopwatch();
|
||||
if (sw.getStartTime() > 0) {
|
||||
long base = sw.getStartTime();
|
||||
if (sw.getPauseTime() > 0) {
|
||||
base += SystemClock.elapsedRealtime() - sw.getPauseTime();
|
||||
// We're not done pausing yet, so don't reset mPauseTime.
|
||||
}
|
||||
chronometer.setBase(base);
|
||||
}
|
||||
if (isStopwatchRunning()) {
|
||||
chronometer.start();
|
||||
// Note: mChronometer.isRunning() will return false at this point and
|
||||
// in other upcoming lifecycle methods because it is not yet visible
|
||||
// (i.e. mVisible == false).
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
super.run();
|
||||
mChronometer.setBase(getStopwatch().getStartTime());
|
||||
mChronometer.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pause() {
|
||||
// Keep this call and the call to Stopwatch.pause() close together to minimize the time delta.
|
||||
mChronometer.stop();
|
||||
super.pause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
mChronometer.stop();
|
||||
mChronometer.setBase(SystemClock.elapsedRealtime());
|
||||
super.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addNewLap(String currentLapTotalText) {
|
||||
if (!mChronometer.isRunning()) {
|
||||
Log.d(TAG, "Cannot add new lap");
|
||||
return;
|
||||
}
|
||||
super.addNewLap(currentLapTotalText);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the state of the stopwatch when we're in a resumed and visible state,
|
||||
* or when we're going through a rotation
|
||||
*/
|
||||
@Override
|
||||
public boolean isStopwatchRunning() {
|
||||
return mChronometer.isRunning() || super.isStopwatchRunning();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user