From 5f138f2756f2a87ba5ffd136140f892dca9de90c Mon Sep 17 00:00:00 2001 From: Phillip Hsu Date: Thu, 30 Jun 2016 16:21:21 -0700 Subject: [PATCH] Implement Parcelable for Alarm, snackbar undo working when deleted --- app/build.gradle | 2 +- .../java/com/philliphsu/clock2/Alarm.java | 61 ++++++++++++++++++- .../clock2/alarms/AlarmsFragment.java | 9 +-- .../clock2/editalarm/EditAlarmActivity.java | 12 ++-- 4 files changed, 73 insertions(+), 11 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index a73a32f..791a8d4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -25,7 +25,7 @@ dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' testCompile 'org.mockito:mockito-core:1.10.19' - testCompile 'org.robolectric:robolectric:3.0' + testCompile 'org.robolectric:robolectric:3.0' // TODO: delete, not in use provided 'com.google.auto.value:auto-value:1.2' apt 'com.google.auto.value:auto-value:1.2' compile 'com.android.support:appcompat-v7:23.2.1' diff --git a/app/src/main/java/com/philliphsu/clock2/Alarm.java b/app/src/main/java/com/philliphsu/clock2/Alarm.java index f036f1e..8d9eca4 100644 --- a/app/src/main/java/com/philliphsu/clock2/Alarm.java +++ b/app/src/main/java/com/philliphsu/clock2/Alarm.java @@ -1,5 +1,7 @@ package com.philliphsu.clock2; +import android.os.Parcel; +import android.os.Parcelable; import android.support.annotation.NonNull; import com.google.auto.value.AutoValue; @@ -18,7 +20,7 @@ import static com.philliphsu.clock2.DaysOfWeek.SUNDAY; * Created by Phillip Hsu on 5/26/2016. */ @AutoValue -public abstract class Alarm implements JsonSerializable { +public abstract class Alarm implements JsonSerializable, Parcelable { private static final int MAX_MINUTES_CAN_SNOOZE = 30; // =================== MUTABLE ======================= @@ -206,6 +208,63 @@ public abstract class Alarm implements JsonSerializable { throw new UnsupportedOperationException(); } + // ============================ PARCELABLE ============================== + // Unfortunately, we can't use the Parcelable extension for AutoValue because + // our model isn't totally immutable. Our mutable properties will be left + // out of the generated class. + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(hour()); + dest.writeInt(minutes()); + dest.writeString(label()); + dest.writeString(ringtone()); + dest.writeInt(vibrates() ? 1 : 0); + // Mutable fields must be written after the immutable fields, + // because when we recreate the object, we can't initialize + // those mutable fields until after we call build(). Values + // in the parcel are read in the order they were written. + dest.writeLong(id); + dest.writeLong(snoozingUntilMillis); + dest.writeInt(enabled ? 1 : 0); + dest.writeBooleanArray(recurringDays); + } + + private static Alarm create(Parcel in) { + Alarm alarm = Alarm.builder() + .hour(in.readInt()) + .minutes(in.readInt()) + .label(in.readString()) + .ringtone(in.readString()) + .vibrates(in.readInt() != 0) + .build(); + alarm.id = in.readLong(); + alarm.snoozingUntilMillis = in.readLong(); + alarm.enabled = in.readInt() != 0; + in.readBooleanArray(alarm.recurringDays); + return alarm; + } + + public static final Parcelable.Creator CREATOR + = new Parcelable.Creator() { + @Override + public Alarm createFromParcel(Parcel source) { + return Alarm.create(source); + } + + @Override + public Alarm[] newArray(int size) { + return new Alarm[size]; + } + }; + + // ====================================================================== + @AutoValue.Builder public abstract static class Builder { public abstract Builder hour(int hour); diff --git a/app/src/main/java/com/philliphsu/clock2/alarms/AlarmsFragment.java b/app/src/main/java/com/philliphsu/clock2/alarms/AlarmsFragment.java index ad24586..1554022 100644 --- a/app/src/main/java/com/philliphsu/clock2/alarms/AlarmsFragment.java +++ b/app/src/main/java/com/philliphsu/clock2/alarms/AlarmsFragment.java @@ -127,10 +127,10 @@ public class AlarmsFragment extends Fragment implements LoaderCallbacks, case REQUEST_CREATE_ALARM: getLoaderManager().restartLoader(0, null, this); case REQUEST_EDIT_ALARM: - if (data != null && data.getBooleanExtra( - EditAlarmActivity.EXTRA_ALARM_DELETED, false)) { - // TODO: Pass in the old alarm into the intent and access it here? - onListItemDeleted(null); + Alarm deletedAlarm; + if (data != null && (deletedAlarm = data.getParcelableExtra( + EditAlarmActivity.EXTRA_DELETED_ALARM)) != null) { + onListItemDeleted(deletedAlarm); } getLoaderManager().restartLoader(0, null, this); break; @@ -149,6 +149,7 @@ public class AlarmsFragment extends Fragment implements LoaderCallbacks, // TODO: This doesn't need to be defined in the interface. // TODO: Rename to showDeletedSnackbar() or something + // TODO: This needs to prompt a reload of the list. @Override public void onListItemDeleted(final Alarm item) { Snackbar.make(getActivity().findViewById(R.id.main_content), diff --git a/app/src/main/java/com/philliphsu/clock2/editalarm/EditAlarmActivity.java b/app/src/main/java/com/philliphsu/clock2/editalarm/EditAlarmActivity.java index 68f62fa..9fd0d47 100644 --- a/app/src/main/java/com/philliphsu/clock2/editalarm/EditAlarmActivity.java +++ b/app/src/main/java/com/philliphsu/clock2/editalarm/EditAlarmActivity.java @@ -58,7 +58,7 @@ public class EditAlarmActivity extends BaseActivity implements AlarmNumpad.KeyLi LoaderManager.LoaderCallbacks { private static final String TAG = "EditAlarmActivity"; public static final String EXTRA_ALARM_ID = "com.philliphsu.clock2.editalarm.extra.ALARM_ID"; - public static final String EXTRA_ALARM_DELETED = "com.philliphsu.clock2.editalarm.extra.ALARM_DELETED"; + public static final String EXTRA_DELETED_ALARM = "com.philliphsu.clock2.editalarm.extra.DELETED_ALARM"; private static final RelativeSizeSpan AMPM_SIZE_SPAN = new RelativeSizeSpan(0.5f); private static final int REQUEST_PICK_RINGTONE = 0; @@ -260,13 +260,15 @@ public class EditAlarmActivity extends BaseActivity implements AlarmNumpad.KeyLi if (mOldAlarm != null) { if (mOldAlarm.isEnabled()) { cancelAlarm(mOldAlarm, false); + // Re-enable in case this is restored so + // the alarm is scheduled again + mOldAlarm.setEnabled(true); } mDatabaseManager.deleteAlarm(mOldAlarm); + Intent intent = new Intent(); + intent.putExtra(EXTRA_DELETED_ALARM, mOldAlarm); + setResult(RESULT_OK, intent); } - Intent intent = new Intent(); - // TODO: Pass in the old alarm into the intent? - intent.putExtra(EXTRA_ALARM_DELETED, true); - setResult(RESULT_OK, intent); showEditorClosed(); }