Hide alarm cursors

pull/189/head
Alex Baker 12 years ago
parent e30f552e6e
commit 328877a2d6

@ -13,7 +13,7 @@ import android.widget.ImageButton;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import com.todoroo.andlib.data.TodorooCursor; import com.todoroo.andlib.data.Callback;
import com.todoroo.andlib.utility.DateUtilities; import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.data.Metadata; import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.data.Task; import com.todoroo.astrid.data.Task;
@ -53,14 +53,12 @@ public final class AlarmControlSet extends TaskEditControlSet {
@Override @Override
protected void readFromTaskOnInitialize() { protected void readFromTaskOnInitialize() {
alertsContainer.removeAllViews(); alertsContainer.removeAllViews();
TodorooCursor<Metadata> cursor = alarmService.getAlarms(model.getId()); alarmService.getAlarms(model.getId(), new Callback<Metadata>() {
try { @Override
for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { public void apply(Metadata entry) {
addAlarm(newDate(cursor.get(AlarmFields.TIME))); addAlarm(newDate(entry.getValue(AlarmFields.TIME)));
}
} finally {
cursor.close();
} }
});
} }
@Override @Override

@ -11,7 +11,7 @@ import android.content.ContentValues;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import com.todoroo.andlib.data.TodorooCursor; import com.todoroo.andlib.data.Callback;
import com.todoroo.andlib.sql.Criterion; import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.Join; import com.todoroo.andlib.sql.Join;
import com.todoroo.andlib.sql.Order; import com.todoroo.andlib.sql.Order;
@ -26,14 +26,13 @@ import com.todoroo.astrid.reminders.Notifications;
import com.todoroo.astrid.reminders.ReminderService; import com.todoroo.astrid.reminders.ReminderService;
import com.todoroo.astrid.service.SynchronizeMetadataCallback; import com.todoroo.astrid.service.SynchronizeMetadataCallback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tasks.injection.ForApplication; import org.tasks.injection.ForApplication;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashSet; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -47,12 +46,16 @@ import javax.inject.Singleton;
@Singleton @Singleton
public class AlarmService { public class AlarmService {
private static final Logger log = LoggerFactory.getLogger(AlarmService.class); private static final long NO_ALARM = Long.MAX_VALUE;
// --- data retrieval
private MetadataDao metadataDao; private final MetadataDao metadataDao;
private final Context context; private final Context context;
private final Callback<Metadata> scheduleAlarm = new Callback<Metadata>() {
@Override
public void apply(Metadata alarm) {
scheduleAlarm(alarm);
}
};
@Inject @Inject
public AlarmService(MetadataDao metadataDao, @ForApplication Context context) { public AlarmService(MetadataDao metadataDao, @ForApplication Context context) {
@ -60,11 +63,8 @@ public class AlarmService {
this.context = context; this.context = context;
} }
/** public void getAlarms(long taskId, Callback<Metadata> callback) {
* Return alarms for the given task. PLEASE CLOSE THE CURSOR! metadataDao.query(callback, Query.select(
*/
public TodorooCursor<Metadata> getAlarms(long taskId) {
return metadataDao.query(Query.select(
Metadata.PROPERTIES).where(MetadataCriteria.byTaskAndwithKey( Metadata.PROPERTIES).where(MetadataCriteria.byTaskAndwithKey(
taskId, AlarmFields.METADATA_KEY)).orderBy(Order.asc(AlarmFields.TIME))); taskId, AlarmFields.METADATA_KEY)).orderBy(Order.asc(AlarmFields.TIME)));
} }
@ -73,8 +73,8 @@ public class AlarmService {
* Save the given array of alarms into the database * Save the given array of alarms into the database
* @return true if data was changed * @return true if data was changed
*/ */
public boolean synchronizeAlarms(final long taskId, LinkedHashSet<Long> alarms) { public boolean synchronizeAlarms(final long taskId, Set<Long> alarms) {
ArrayList<Metadata> metadata = new ArrayList<>(); List<Metadata> metadata = new ArrayList<>();
for(Long alarm : alarms) { for(Long alarm : alarms) {
Metadata item = new Metadata(); Metadata item = new Metadata();
item.setKey(AlarmFields.METADATA_KEY); item.setKey(AlarmFields.METADATA_KEY);
@ -85,7 +85,7 @@ public class AlarmService {
final AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); final AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
boolean changed = synchronizeMetadata(taskId, metadata, Metadata.KEY.eq(AlarmFields.METADATA_KEY), new SynchronizeMetadataCallback() { boolean changed = synchronizeMetadata(taskId, metadata, new SynchronizeMetadataCallback() {
@Override @Override
public void beforeDeleteMetadata(Metadata m) { public void beforeDeleteMetadata(Metadata m) {
// Cancel the alarm before the metadata is deleted // Cancel the alarm before the metadata is deleted
@ -102,22 +102,14 @@ public class AlarmService {
// --- alarm scheduling // --- alarm scheduling
/** private void getActiveAlarms(Callback<Metadata> callback) {
* Gets a listing of all alarms that are active metadataDao.query(callback, Query.select(Metadata.ID, Metadata.TASK, AlarmFields.TIME).
* @return todoroo cursor. PLEASE CLOSE THIS CURSOR!
*/
private TodorooCursor<Metadata> getActiveAlarms() {
return metadataDao.query(Query.select(Metadata.ID, Metadata.TASK, AlarmFields.TIME).
join(Join.inner(Task.TABLE, Metadata.TASK.eq(Task.ID))). join(Join.inner(Task.TABLE, Metadata.TASK.eq(Task.ID))).
where(Criterion.and(TaskCriteria.isActive(), MetadataCriteria.withKey(AlarmFields.METADATA_KEY)))); where(Criterion.and(TaskCriteria.isActive(), MetadataCriteria.withKey(AlarmFields.METADATA_KEY))));
} }
/** private void getActiveAlarmsForTask(long taskId, Callback<Metadata> callback) {
* Gets a listing of alarms by task metadataDao.query(callback, Query.select(Metadata.ID, Metadata.TASK, AlarmFields.TIME).
* @return todoroo cursor. PLEASE CLOSE THIS CURSOR!
*/
private TodorooCursor<Metadata> getActiveAlarmsForTask(long taskId) {
return metadataDao.query(Query.select(Metadata.ID, Metadata.TASK, AlarmFields.TIME).
join(Join.inner(Task.TABLE, Metadata.TASK.eq(Task.ID))). join(Join.inner(Task.TABLE, Metadata.TASK.eq(Task.ID))).
where(Criterion.and(TaskCriteria.isActive(), where(Criterion.and(TaskCriteria.isActive(),
MetadataCriteria.byTaskAndwithKey(taskId, AlarmFields.METADATA_KEY)))); MetadataCriteria.byTaskAndwithKey(taskId, AlarmFields.METADATA_KEY))));
@ -127,37 +119,14 @@ public class AlarmService {
* Schedules all alarms * Schedules all alarms
*/ */
public void scheduleAllAlarms() { public void scheduleAllAlarms() {
TodorooCursor<Metadata> cursor = getActiveAlarms(); getActiveAlarms(scheduleAlarm);
try {
for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
Metadata alarm = new Metadata(cursor);
scheduleAlarm(alarm);
} }
} catch (Exception e) {
// suppress
log.error(e.getMessage(), e);
} finally {
cursor.close();
}
}
private static final long NO_ALARM = Long.MAX_VALUE;
/** /**
* Schedules alarms for a single task * Schedules alarms for a single task
*/ */
public void scheduleAlarms(long taskId) { private void scheduleAlarms(long taskId) {
TodorooCursor<Metadata> cursor = getActiveAlarmsForTask(taskId); getActiveAlarmsForTask(taskId, scheduleAlarm);
try {
for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
Metadata alarm = new Metadata(cursor);
scheduleAlarm(alarm);
}
} catch (Exception e) {
log.error(e.getMessage(), e);
} finally {
cursor.close();
}
} }
private PendingIntent pendingIntentForAlarm(Metadata alarm, long taskId) { private PendingIntent pendingIntentForAlarm(Metadata alarm, long taskId) {
@ -191,10 +160,9 @@ public class AlarmService {
} }
} }
private boolean synchronizeMetadata(long taskId, ArrayList<Metadata> metadata, private boolean synchronizeMetadata(long taskId, List<Metadata> metadata, final SynchronizeMetadataCallback callback) {
Criterion metadataCriterion, SynchronizeMetadataCallback callback) { final boolean[] dirty = new boolean[1];
boolean dirty = false; final Set<ContentValues> newMetadataValues = new HashSet<>();
HashSet<ContentValues> newMetadataValues = new HashSet<>();
for(Metadata metadatum : metadata) { for(Metadata metadatum : metadata) {
metadatum.setTask(taskId); metadatum.setTask(taskId);
metadatum.clearValue(Metadata.CREATION_DATE); metadatum.clearValue(Metadata.CREATION_DATE);
@ -210,12 +178,9 @@ public class AlarmService {
newMetadataValues.add(values); newMetadataValues.add(values);
} }
TodorooCursor<Metadata> cursor = metadataDao.query(Query.select(Metadata.PROPERTIES).where(Criterion.and(MetadataCriteria.byTask(taskId), metadataDao.byTaskAndKey(taskId, AlarmFields.METADATA_KEY, new Callback<Metadata>() {
metadataCriterion))); @Override
try { public void apply(Metadata item) {
// try to find matches within our metadata list
for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
Metadata item = new Metadata(cursor);
long id = item.getId(); long id = item.getId();
// clear item id when matching with incoming values // clear item id when matching with incoming values
@ -225,20 +190,17 @@ public class AlarmService {
if(newMetadataValues.contains(itemMergedValues)) { if(newMetadataValues.contains(itemMergedValues)) {
newMetadataValues.remove(itemMergedValues); newMetadataValues.remove(itemMergedValues);
continue; } else {
}
// not matched. cut it // not matched. cut it
item.setId(id); item.setId(id);
if (callback != null) { if (callback != null) {
callback.beforeDeleteMetadata(item); callback.beforeDeleteMetadata(item);
} }
metadataDao.delete(id); metadataDao.delete(id);
dirty = true; dirty[0] = true;
} }
} finally {
cursor.close();
} }
});
// everything that remains shall be written // everything that remains shall be written
for(ContentValues values : newMetadataValues) { for(ContentValues values : newMetadataValues) {
@ -246,9 +208,9 @@ public class AlarmService {
item.setCreationDate(DateUtilities.now()); item.setCreationDate(DateUtilities.now());
item.mergeWith(values); item.mergeWith(values);
metadataDao.persist(item); metadataDao.persist(item);
dirty = true; dirty[0] = true;
} }
return dirty; return dirty[0];
} }
} }

@ -8,7 +8,7 @@ package com.todoroo.astrid.alarms;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import com.todoroo.andlib.data.TodorooCursor; import com.todoroo.andlib.data.Callback;
import com.todoroo.andlib.service.ContextManager; import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.utility.DateUtilities; import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.api.AstridApiConstants; import com.todoroo.astrid.api.AstridApiConstants;
@ -17,6 +17,7 @@ import com.todoroo.astrid.data.Metadata;
import org.tasks.injection.InjectingBroadcastReceiver; import org.tasks.injection.InjectingBroadcastReceiver;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.Set;
import javax.inject.Inject; import javax.inject.Inject;
@ -34,31 +35,23 @@ public class AlarmTaskRepeatListener extends InjectingBroadcastReceiver {
return; return;
} }
long oldDueDate = intent.getLongExtra(AstridApiConstants.EXTRAS_OLD_DUE_DATE, 0); long oldDueDateExtra = intent.getLongExtra(AstridApiConstants.EXTRAS_OLD_DUE_DATE, 0);
if(oldDueDate == 0) { final long oldDueDate = oldDueDateExtra == 0 ? DateUtilities.now() : oldDueDateExtra;
oldDueDate = DateUtilities.now(); final long newDueDate = intent.getLongExtra(AstridApiConstants.EXTRAS_NEW_DUE_DATE, -1);
}
long newDueDate = intent.getLongExtra(AstridApiConstants.EXTRAS_NEW_DUE_DATE, -1);
if(newDueDate <= 0 || newDueDate <= oldDueDate) {
return;
}
TodorooCursor<Metadata> cursor = alarmService.getAlarms(taskId); if(newDueDate <= 0 || newDueDate <= oldDueDate) {
try {
if(cursor.getCount() == 0) {
return; return;
} }
LinkedHashSet<Long> alarms = new LinkedHashSet<>(cursor.getCount()); final Set<Long> alarms = new LinkedHashSet<>();
for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { alarmService.getAlarms(taskId, new Callback<Metadata>() {
Metadata metadata = new Metadata(cursor); @Override
public void apply(Metadata metadata) {
alarms.add(metadata.getValue(AlarmFields.TIME) + (newDueDate - oldDueDate)); alarms.add(metadata.getValue(AlarmFields.TIME) + (newDueDate - oldDueDate));
} }
});
if (!alarms.isEmpty()) {
alarmService.synchronizeAlarms(taskId, alarms); alarmService.synchronizeAlarms(taskId, alarms);
} finally {
cursor.close();
} }
} }
} }

@ -5,6 +5,7 @@
*/ */
package com.todoroo.astrid.dao; package com.todoroo.astrid.dao;
import com.todoroo.andlib.data.Callback;
import com.todoroo.andlib.data.DatabaseDao; import com.todoroo.andlib.data.DatabaseDao;
import com.todoroo.andlib.sql.Criterion; import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.Join; import com.todoroo.andlib.sql.Join;
@ -52,7 +53,6 @@ public class MetadataDao extends DatabaseDao<Metadata> {
public static Criterion byTaskAndwithKey(long taskId, String key) { public static Criterion byTaskAndwithKey(long taskId, String key) {
return Criterion.and(withKey(key), byTask(taskId)); return Criterion.and(withKey(key), byTask(taskId));
} }
} }
@Override @Override
@ -74,5 +74,10 @@ public class MetadataDao extends DatabaseDao<Metadata> {
deleteWhere(Metadata.ID.in(Query.select(Metadata.ID).from(Metadata.TABLE).join(Join.left(Task.TABLE, deleteWhere(Metadata.ID.in(Query.select(Metadata.ID).from(Metadata.TABLE).join(Join.left(Task.TABLE,
Metadata.TASK.eq(Task.ID))).where(Task.TITLE.isNull()))); Metadata.TASK.eq(Task.ID))).where(Task.TITLE.isNull())));
} }
public void byTaskAndKey(long taskId, String key, Callback<Metadata> callback) {
query(callback, Query.select(Metadata.PROPERTIES).where(
Criterion.and(Metadata.TASK.eq(taskId), Metadata.KEY.eq(key))));
}
} }

Loading…
Cancel
Save