Created AsyncDatabaseChangeHandler
This commit is contained in:
parent
066ac67325
commit
7b0a32938e
@ -0,0 +1,128 @@
|
|||||||
|
package com.philliphsu.clock2;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
|
||||||
|
import com.philliphsu.clock2.alarms.ScrollHandler;
|
||||||
|
import com.philliphsu.clock2.model.DatabaseTableManager;
|
||||||
|
import com.philliphsu.clock2.model.ObjectWithId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Phillip Hsu on 7/1/2016.
|
||||||
|
*/
|
||||||
|
public abstract class AsyncDatabaseChangeHandler<
|
||||||
|
T extends ObjectWithId,
|
||||||
|
TM extends DatabaseTableManager<T>> {
|
||||||
|
private static final String TAG = "AsyncDatabaseChangeHandler";
|
||||||
|
|
||||||
|
private final Context mAppContext;
|
||||||
|
private final ScrollHandler mScrollHandler;
|
||||||
|
private final TM mTableManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param context the Context from which we get the application context
|
||||||
|
*/
|
||||||
|
public AsyncDatabaseChangeHandler(Context context, ScrollHandler scrollHandler) {
|
||||||
|
mAppContext = context.getApplicationContext(); // to prevent memory leaks
|
||||||
|
mScrollHandler = scrollHandler;
|
||||||
|
mTableManager = getTableManager(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void asyncInsert(final T item) {
|
||||||
|
new InsertAsyncTask(item).execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void asyncUpdate(final long id, final T newItem) {
|
||||||
|
new UpdateAsyncTask(id, newItem).execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void asyncDelete(final T item) {
|
||||||
|
// TODO: If we want to scroll somewhere after we delete this item, we can
|
||||||
|
// create a DeleteAsyncTask subclass of the BaseAsyncTask. This involves
|
||||||
|
// using a Long result, however.
|
||||||
|
new AsyncTask<Void, Void, Integer>() {
|
||||||
|
@Override
|
||||||
|
protected Integer doInBackground(Void... params) {
|
||||||
|
return mTableManager.deleteItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Integer integer) {
|
||||||
|
onPostAsyncDelete(integer, item);
|
||||||
|
}
|
||||||
|
}.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final Context getContext() {
|
||||||
|
return mAppContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract TM getTableManager(Context context);
|
||||||
|
|
||||||
|
protected abstract void onPostAsyncDelete(Integer result, T item);
|
||||||
|
|
||||||
|
protected abstract void onPostAsyncInsert(Long result, T item);
|
||||||
|
|
||||||
|
protected abstract void onPostAsyncUpdate(Long result, T item);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Insert and update AsyncTasks
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created because the code in insert and update AsyncTasks are exactly the same.
|
||||||
|
*/
|
||||||
|
private abstract class BaseAsyncTask extends AsyncTask<Void, Void, Long> {
|
||||||
|
final T mItem;
|
||||||
|
|
||||||
|
BaseAsyncTask(T item) {
|
||||||
|
mItem = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Long result) {
|
||||||
|
if (mScrollHandler != null) {
|
||||||
|
// Prepare to scroll to this alarm
|
||||||
|
mScrollHandler.setScrollToStableId(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class InsertAsyncTask extends BaseAsyncTask {
|
||||||
|
InsertAsyncTask(T item) {
|
||||||
|
super(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Long doInBackground(Void... params) {
|
||||||
|
return mTableManager.insertItem(mItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Long result) {
|
||||||
|
super.onPostExecute(result);
|
||||||
|
onPostAsyncInsert(result, mItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class UpdateAsyncTask extends BaseAsyncTask {
|
||||||
|
private final long mId;
|
||||||
|
|
||||||
|
UpdateAsyncTask(long id, T item) {
|
||||||
|
super(item);
|
||||||
|
mId = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Long doInBackground(Void... params) {
|
||||||
|
mTableManager.updateItem(mId, mItem);
|
||||||
|
return mId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Long result) {
|
||||||
|
super.onPostExecute(result);
|
||||||
|
onPostAsyncUpdate(result, mItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,25 +1,23 @@
|
|||||||
package com.philliphsu.clock2;
|
package com.philliphsu.clock2;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.support.design.widget.Snackbar;
|
import android.support.design.widget.Snackbar;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import com.philliphsu.clock2.alarms.ScrollHandler;
|
import com.philliphsu.clock2.alarms.ScrollHandler;
|
||||||
import com.philliphsu.clock2.model.DatabaseManager;
|
import com.philliphsu.clock2.model.AlarmsTableManager;
|
||||||
import com.philliphsu.clock2.util.AlarmController;
|
import com.philliphsu.clock2.util.AlarmController;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Phillip Hsu on 7/1/2016.
|
* Created by Phillip Hsu on 7/1/2016.
|
||||||
*
|
*
|
||||||
* TODO: Generify this class for any item.
|
* TODO: Rename to AsyncAlarmChangeHandler
|
||||||
|
* TODO: Consider making an AsyncDatabaseChangeHandlerWithSnackbar abstract class
|
||||||
*/
|
*/
|
||||||
public final class AsyncItemChangeHandler {
|
public final class AsyncItemChangeHandler extends AsyncDatabaseChangeHandler<Alarm, AlarmsTableManager> {
|
||||||
private static final String TAG = "AsyncItemChangeHandler";
|
private static final String TAG = "AsyncItemChangeHandler";
|
||||||
|
|
||||||
private final Context mContext;
|
|
||||||
private final View mSnackbarAnchor;
|
private final View mSnackbarAnchor;
|
||||||
private final ScrollHandler mScrollHandler;
|
|
||||||
private final AlarmController mAlarmController;
|
private final AlarmController mAlarmController;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -29,108 +27,41 @@ public final class AsyncItemChangeHandler {
|
|||||||
public AsyncItemChangeHandler(Context context, View snackbarAnchor,
|
public AsyncItemChangeHandler(Context context, View snackbarAnchor,
|
||||||
ScrollHandler scrollHandler,
|
ScrollHandler scrollHandler,
|
||||||
AlarmController alarmController) {
|
AlarmController alarmController) {
|
||||||
mContext = context.getApplicationContext(); // to prevent memory leaks
|
super(context, scrollHandler);
|
||||||
mSnackbarAnchor = snackbarAnchor;
|
mSnackbarAnchor = snackbarAnchor;
|
||||||
mScrollHandler = scrollHandler;
|
|
||||||
mAlarmController = alarmController;
|
mAlarmController = alarmController;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void asyncAddAlarm(final Alarm alarm) {
|
|
||||||
new InsertAlarmAsyncTask(alarm).execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We only need one Alarm param because we called newAlarm.setId(oldAlarm.id())
|
|
||||||
* when we were in the edit activity.
|
|
||||||
* TODO: Consider changing the signature of updateAlarm() in DatabaseManager and
|
|
||||||
* AlarmDatabaseHelper to only require one Alarm param.
|
|
||||||
*/
|
|
||||||
public void asyncUpdateAlarm(final Alarm newAlarm) {
|
|
||||||
new UpdateAlarmAsyncTask(newAlarm).execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void asyncRemoveAlarm(final Alarm alarm) {
|
|
||||||
new AsyncTask<Void, Void, Integer>() {
|
|
||||||
@Override
|
@Override
|
||||||
protected Integer doInBackground(Void... params) {
|
protected AlarmsTableManager getTableManager(Context context) {
|
||||||
return DatabaseManager.getInstance(mContext).deleteAlarm(alarm);
|
return new AlarmsTableManager(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(Integer integer) {
|
protected void onPostAsyncDelete(Integer result, final Alarm alarm) {
|
||||||
mAlarmController.cancelAlarm(alarm, false);
|
mAlarmController.cancelAlarm(alarm, false);
|
||||||
if (mSnackbarAnchor != null) {
|
if (mSnackbarAnchor != null) {
|
||||||
// TODO: Consider adding delay to allow the alarm item animation
|
// TODO: Consider adding delay to allow the alarm item animation
|
||||||
// to finish first before we show the snackbar. Inbox app does this.
|
// to finish first before we show the snackbar. Inbox app does this.
|
||||||
String message = mContext.getString(R.string.snackbar_item_deleted,
|
String message = getContext().getString(R.string.snackbar_item_deleted,
|
||||||
mContext.getString(R.string.alarm));
|
getContext().getString(R.string.alarm));
|
||||||
Snackbar.make(mSnackbarAnchor, message, Snackbar.LENGTH_LONG)
|
Snackbar.make(mSnackbarAnchor, message, Snackbar.LENGTH_LONG)
|
||||||
.setAction(R.string.snackbar_undo_item_deleted, new View.OnClickListener() {
|
.setAction(R.string.snackbar_undo_item_deleted, new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
asyncAddAlarm(alarm);
|
asyncInsert(alarm);
|
||||||
}
|
}
|
||||||
}).show();
|
}).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
@Override
|
||||||
// Insert and update AsyncTasks
|
protected void onPostAsyncInsert(Long result, Alarm alarm) {
|
||||||
////////////////////////////////////////////////////////////
|
mAlarmController.scheduleAlarm(alarm, true);
|
||||||
|
|
||||||
/**
|
|
||||||
* Created because the code in insert and update AsyncTasks are exactly the same.
|
|
||||||
*/
|
|
||||||
private abstract class BaseAsyncTask extends AsyncTask<Void, Void, Long> {
|
|
||||||
private final Alarm mAlarm;
|
|
||||||
|
|
||||||
BaseAsyncTask(Alarm alarm) {
|
|
||||||
mAlarm = alarm;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(Long result) {
|
protected void onPostAsyncUpdate(Long result, Alarm alarm) {
|
||||||
// TODO: Consider adding delay to allow the alarm item animation
|
mAlarmController.scheduleAlarm(alarm, true);
|
||||||
// to finish first before we show the snackbar. Inbox app does this.
|
|
||||||
mAlarmController.scheduleAlarm(mAlarm, true);
|
|
||||||
if (mScrollHandler != null) {
|
|
||||||
// Prepare to scroll to this alarm
|
|
||||||
mScrollHandler.setScrollToStableId(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final Long insertAlarm() {
|
|
||||||
return DatabaseManager.getInstance(mContext).insertAlarm(mAlarm);
|
|
||||||
}
|
|
||||||
|
|
||||||
final Long updateAlarm() {
|
|
||||||
long id = mAlarm.id();
|
|
||||||
DatabaseManager.getInstance(mContext).updateAlarm(id, mAlarm);
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class InsertAlarmAsyncTask extends BaseAsyncTask {
|
|
||||||
InsertAlarmAsyncTask(Alarm alarm) {
|
|
||||||
super(alarm);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Long doInBackground(Void... params) {
|
|
||||||
return insertAlarm();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class UpdateAlarmAsyncTask extends BaseAsyncTask {
|
|
||||||
UpdateAlarmAsyncTask(Alarm alarm) {
|
|
||||||
super(alarm);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Long doInBackground(Void... params) {
|
|
||||||
return updateAlarm();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,7 +18,8 @@ import butterknife.Bind;
|
|||||||
/**
|
/**
|
||||||
* Created by Phillip Hsu on 7/26/2016.
|
* Created by Phillip Hsu on 7/26/2016.
|
||||||
*/
|
*/
|
||||||
public abstract class RecyclerViewFragment<T extends ObjectWithId,
|
public abstract class RecyclerViewFragment<
|
||||||
|
T extends ObjectWithId,
|
||||||
VH extends BaseViewHolder<T>,
|
VH extends BaseViewHolder<T>,
|
||||||
C extends BaseItemCursor<T>,
|
C extends BaseItemCursor<T>,
|
||||||
A extends BaseCursorAdapter<T, VH, C>>
|
A extends BaseCursorAdapter<T, VH, C>>
|
||||||
|
|||||||
@ -138,7 +138,7 @@ public class AlarmsFragment extends RecyclerViewFragment<
|
|||||||
if (data.getBooleanExtra(EditAlarmActivity.EXTRA_IS_DELETING, false)) {
|
if (data.getBooleanExtra(EditAlarmActivity.EXTRA_IS_DELETING, false)) {
|
||||||
// TODO: Should we delay this too? It seems animations run
|
// TODO: Should we delay this too? It seems animations run
|
||||||
// some of the time.
|
// some of the time.
|
||||||
mAsyncItemChangeHandler.asyncRemoveAlarm(alarm);
|
mAsyncItemChangeHandler.asyncDelete(alarm);
|
||||||
} else {
|
} else {
|
||||||
// TODO: Increase the delay, because update animation is
|
// TODO: Increase the delay, because update animation is
|
||||||
// more elusive than insert.
|
// more elusive than insert.
|
||||||
@ -206,15 +206,15 @@ public class AlarmsFragment extends RecyclerViewFragment<
|
|||||||
}
|
}
|
||||||
|
|
||||||
void asyncAddAlarm() {
|
void asyncAddAlarm() {
|
||||||
mAsyncItemChangeHandler.asyncAddAlarm(mAlarm);
|
mAsyncItemChangeHandler.asyncInsert(mAlarm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void asyncUpdateAlarm() {
|
void asyncUpdateAlarm() {
|
||||||
mAsyncItemChangeHandler.asyncUpdateAlarm(mAlarm);
|
mAsyncItemChangeHandler.asyncUpdate(mAlarm.getId(), mAlarm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void asyncRemoveAlarm() {
|
void asyncRemoveAlarm() {
|
||||||
mAsyncItemChangeHandler.asyncRemoveAlarm(mAlarm);
|
mAsyncItemChangeHandler.asyncDelete(mAlarm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,6 @@ import com.philliphsu.clock2.RecyclerViewFragment;
|
|||||||
import com.philliphsu.clock2.Timer;
|
import com.philliphsu.clock2.Timer;
|
||||||
import com.philliphsu.clock2.edittimer.EditTimerActivity;
|
import com.philliphsu.clock2.edittimer.EditTimerActivity;
|
||||||
import com.philliphsu.clock2.model.TimerCursor;
|
import com.philliphsu.clock2.model.TimerCursor;
|
||||||
import com.philliphsu.clock2.model.TimerDatabaseHelper;
|
|
||||||
import com.philliphsu.clock2.model.TimersListCursorLoader;
|
import com.philliphsu.clock2.model.TimersListCursorLoader;
|
||||||
|
|
||||||
public class TimersFragment extends RecyclerViewFragment<
|
public class TimersFragment extends RecyclerViewFragment<
|
||||||
@ -23,8 +22,6 @@ public class TimersFragment extends RecyclerViewFragment<
|
|||||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
// if (resultCode != Activity.RESULT_OK || data == null)
|
// if (resultCode != Activity.RESULT_OK || data == null)
|
||||||
// return;
|
// return;
|
||||||
TimerDatabaseHelper db = new TimerDatabaseHelper(getActivity());
|
|
||||||
db.insertItem(Timer.create(1, 0, 0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user