Update list counts

Closes #22
pull/120/head
Alex Baker 12 years ago
parent 62c280e532
commit 9789ec05db

@ -201,6 +201,8 @@ public class AstridApiConstants {
*/ */
public static final String BROADCAST_EVENT_TASK_LIST_UPDATED = API_PACKAGE + ".TASK_LIST_UPDATED"; public static final String BROADCAST_EVENT_TASK_LIST_UPDATED = API_PACKAGE + ".TASK_LIST_UPDATED";
public static final String BROADCAST_EVENT_FILTER_LIST_UPDATED = API_PACKAGE + ".FILTER_LIST_UPDATED";
/** /**
* Action name for broadcast intent notifying that task was completed * Action name for broadcast intent notifying that task was completed
* <li> EXTRAS_TASK_ID id of the task * <li> EXTRAS_TASK_ID id of the task

@ -219,4 +219,9 @@ public class Filter extends FilterListItem {
return new Filter[size]; return new Filter[size];
} }
}; };
@Override
public String toString() {
return title;
}
} }

@ -456,24 +456,10 @@ public class TaskListActivity extends AstridActivity implements OnPageChangeList
} }
} }
public void incrementFilterCount(Filter filter) { public void refreshFilterCount() {
FilterListFragment flf = getFilterListFragment(); FilterListFragment flf = getFilterListFragment();
if (flf != null) { if (flf != null) {
flf.adapter.incrementFilterCount(filter); flf.adapter.refreshFilterCount();
}
}
public void decrementFilterCount(Filter filter) {
FilterListFragment flf = getFilterListFragment();
if (flf != null) {
flf.adapter.decrementFilterCount(filter);
}
}
public void refreshFilterCount(Filter filter) {
FilterListFragment flf = getFilterListFragment();
if (flf != null) {
flf.adapter.refreshFilterCount(filter);
} }
} }

@ -956,12 +956,9 @@ public class TaskListFragment extends ListFragment implements OnSortSelectedList
} }
public void onTaskCreated(Task task) { public void onTaskCreated(Task task) {
incrementFilterCount();
} }
protected void onTaskDelete(Task task) { protected void onTaskDelete(Task task) {
decrementFilterCount();
Activity a = getActivity(); Activity a = getActivity();
if (a instanceof AstridActivity) { if (a instanceof AstridActivity) {
AstridActivity activity = (AstridActivity) a; AstridActivity activity = (AstridActivity) a;
@ -975,21 +972,9 @@ public class TaskListFragment extends ListFragment implements OnSortSelectedList
TimerPlugin.updateTimer(ContextManager.getContext(), task, false); TimerPlugin.updateTimer(ContextManager.getContext(), task, false);
} }
public void incrementFilterCount() {
if (getActivity() instanceof TaskListActivity) {
((TaskListActivity) getActivity()).incrementFilterCount(filter);
}
}
public void decrementFilterCount() {
if (getActivity() instanceof TaskListActivity) {
((TaskListActivity) getActivity()).decrementFilterCount(filter);
}
}
public void refreshFilterCount() { public void refreshFilterCount() {
if (getActivity() instanceof TaskListActivity) { if (getActivity() instanceof TaskListActivity) {
((TaskListActivity) getActivity()).refreshFilterCount(filter); ((TaskListActivity) getActivity()).refreshFilterCount();
} }
} }

@ -19,7 +19,6 @@ import android.os.Bundle;
import android.os.Parcelable; import android.os.Parcelable;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -48,12 +47,9 @@ import com.todoroo.astrid.api.FilterWithUpdate;
import com.todoroo.astrid.service.TaskService; import com.todoroo.astrid.service.TaskService;
import org.tasks.R; import org.tasks.R;
import org.tasks.filters.FilterCounter;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -69,6 +65,9 @@ public class FilterAdapter extends ArrayAdapter<Filter> {
@Autowired @Autowired
private TaskService taskService; private TaskService taskService;
@Autowired
private FilterCounter filterCounter;
/** parent activity */ /** parent activity */
protected final Activity activity; protected final Activity activity;
@ -81,6 +80,8 @@ public class FilterAdapter extends ArrayAdapter<Filter> {
/** receiver for new filters */ /** receiver for new filters */
protected final FilterReceiver filterReceiver = new FilterReceiver(); protected final FilterReceiver filterReceiver = new FilterReceiver();
private final FilterListUpdateReceiver filterListUpdateReceiver = new FilterListUpdateReceiver();
/** row layout to inflate */ /** row layout to inflate */
private final int layout; private final int layout;
@ -93,20 +94,6 @@ public class FilterAdapter extends ArrayAdapter<Filter> {
/** whether rows are selectable */ /** whether rows are selectable */
private final boolean selectable; private final boolean selectable;
/** Pattern for matching filter counts in listing titles */
private final Pattern countPattern = Pattern.compile(".* \\((\\d+)\\)$"); //$NON-NLS-1$
private final HashMap<Filter, Integer> filterCounts;
// Previous solution involved a queue of filters and a filterSizeLoadingThread. The filterSizeLoadingThread had
// a few problems: how to make sure that the thread is resumed when the controlling activity is resumed, and
// how to make sure that the the filterQueue does not accumulate filters without being processed. I am replacing
// both the queue and a the thread with a thread pool, which will shut itself off after a second if it has
// nothing to do (corePoolSize == 0, which makes it available for garbage collection), and will wake itself up
// if new filters are queued (obviously it cannot be garbage collected if it is possible for new filters to
// be added).
private final ThreadPoolExecutor filterExecutor = new ThreadPoolExecutor(0, 1, 1, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
public FilterAdapter(Activity activity, int rowLayout) { public FilterAdapter(Activity activity, int rowLayout) {
this(activity, null, rowLayout, false, false); this(activity, null, rowLayout, false, false);
} }
@ -122,7 +109,6 @@ public class FilterAdapter extends ArrayAdapter<Filter> {
this.layout = rowLayout; this.layout = rowLayout;
this.skipIntentFilters = skipIntentFilters; this.skipIntentFilters = skipIntentFilters;
this.selectable = selectable; this.selectable = selectable;
this.filterCounts = new HashMap<>();
inflater = (LayoutInflater) activity.getSystemService( inflater = (LayoutInflater) activity.getSystemService(
Context.LAYOUT_INFLATER_SERVICE); Context.LAYOUT_INFLATER_SERVICE);
@ -134,40 +120,6 @@ public class FilterAdapter extends ArrayAdapter<Filter> {
if(selectable && selection == null) { if(selectable && selection == null) {
setSelection(filter); setSelection(filter);
} }
filterExecutor.submit(new Runnable() {
@Override
public void run() {
try {
int size = -1;
Matcher m = countPattern.matcher(filter.listingTitle);
if(m.find()) {
String countString = m.group(1);
try {
size = Integer.parseInt(countString);
} catch (NumberFormatException e) {
// Count manually
e.printStackTrace();
}
}
if (size < 0) {
size = taskService.countTasks(filter);
filter.listingTitle = filter.listingTitle + (" (" + //$NON-NLS-1$
size + ")"); //$NON-NLS-1$
}
filterCounts.put(filter, size);
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
notifyDataSetChanged();
}
});
} catch (Exception e) {
Log.e("astrid-filter-adapter", "Error loading filter size", e); //$NON-NLS-1$ //$NON-NLS-2$
}
}
});
} }
@Override @Override
@ -178,9 +130,20 @@ public class FilterAdapter extends ArrayAdapter<Filter> {
@Override @Override
public void add(Filter item) { public void add(Filter item) {
super.add(item); super.add(item);
notifyDataSetChanged();
// load sizes // load sizes
filterCounter.registerFilter(item);
offerFilter(item); offerFilter(item);
notifyDataSetChanged();
}
@Override
public void notifyDataSetChanged() {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
FilterAdapter.super.notifyDataSetChanged();
}
});
} }
public void addOrLookup(Filter filter) { public void addOrLookup(Filter filter) {
@ -203,40 +166,14 @@ public class FilterAdapter extends ArrayAdapter<Filter> {
} }
} }
public void adjustFilterCount(Filter filter, int delta) { public void refreshFilterCount() {
int filterCount = 0; filterCounter.refreshFilterCounts(new Runnable() {
if (filterCounts.containsKey(filter)) {
filterCount = filterCounts.get(filter);
}
int newCount = Math.max(filterCount + delta, 0);
filterCounts.put(filter, newCount);
notifyDataSetChanged();
}
public void incrementFilterCount(Filter filter) {
adjustFilterCount(filter, 1);
}
public void decrementFilterCount(Filter filter) {
adjustFilterCount(filter, -1);
}
public void refreshFilterCount(final Filter filter) {
filterExecutor.submit(new Runnable() {
@Override
public void run() {
int size = taskService.countTasks(filter);
filterCounts.put(filter, size);
activity.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
notifyDataSetChanged(); notifyDataSetChanged();
} }
}); });
} }
});
}
public void setListView(ListView listView) { public void setListView(ListView listView) {
this.listView = listView; this.listView = listView;
@ -271,7 +208,6 @@ public class FilterAdapter extends ArrayAdapter<Filter> {
@Override @Override
public View getView(int position, View convertView, ViewGroup parent) { public View getView(int position, View convertView, ViewGroup parent) {
convertView = newView(convertView, parent); convertView = newView(convertView, parent);
ViewHolder viewHolder = (ViewHolder) convertView.getTag(); ViewHolder viewHolder = (ViewHolder) convertView.getTag();
viewHolder.item = getItem(position); viewHolder.item = getItem(position);
@ -327,6 +263,13 @@ public class FilterAdapter extends ArrayAdapter<Filter> {
* ============================================================= receiver * ============================================================= receiver
* ====================================================================== */ * ====================================================================== */
public class FilterListUpdateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
notifyDataSetChanged();
}
}
/** /**
* Receiver which receives intents to add items to the filter list * Receiver which receives intents to add items to the filter list
* *
@ -383,8 +326,13 @@ public class FilterAdapter extends ArrayAdapter<Filter> {
} }
} }
filterCounter.refreshFilterCounts(new Runnable() {
@Override
public void run() {
notifyDataSetChanged(); notifyDataSetChanged();
} }
});
}
} }
/** /**
@ -403,7 +351,10 @@ public class FilterAdapter extends ArrayAdapter<Filter> {
IntentFilter regularFilter = new IntentFilter(AstridApiConstants.BROADCAST_SEND_FILTERS); IntentFilter regularFilter = new IntentFilter(AstridApiConstants.BROADCAST_SEND_FILTERS);
regularFilter.setPriority(2); regularFilter.setPriority(2);
activity.registerReceiver(filterReceiver, regularFilter); activity.registerReceiver(filterReceiver, regularFilter);
activity.registerReceiver(filterListUpdateReceiver, new IntentFilter(AstridApiConstants.BROADCAST_EVENT_FILTER_LIST_UPDATED));
getLists(); getLists();
refreshFilterCount();
} }
/** /**
@ -411,12 +362,16 @@ public class FilterAdapter extends ArrayAdapter<Filter> {
*/ */
public void unregisterRecevier() { public void unregisterRecevier() {
activity.unregisterReceiver(filterReceiver); activity.unregisterReceiver(filterReceiver);
activity.unregisterReceiver(filterListUpdateReceiver);
} }
/* ====================================================================== /* ======================================================================
* ================================================================ views * ================================================================ views
* ====================================================================== */ * ====================================================================== */
/** Pattern for matching filter counts in listing titles */
private final Pattern countPattern = Pattern.compile(".* \\((\\d+)\\)$"); //$NON-NLS-1$
public void populateView(ViewHolder viewHolder) { public void populateView(ViewHolder viewHolder) {
FilterListItem filter = viewHolder.item; FilterListItem filter = viewHolder.item;
if(filter == null) { if(filter == null) {
@ -438,36 +393,29 @@ public class FilterAdapter extends ArrayAdapter<Filter> {
viewHolder.name.setShadowLayer(0, 0, 0, 0); viewHolder.name.setShadowLayer(0, 0, 0, 0);
} }
String title = filter.listingTitle;
Matcher match = countPattern.matcher(filter.listingTitle);
if(match.matches()) {
title = title.substring(0, title.lastIndexOf(' '));
}
if(!title.equals(viewHolder.name.getText())) {
viewHolder.name.setText(title);
}
// title / size // title / size
int countInt = -1; int countInt = -1;
if(filterCounts.containsKey(filter) || (!TextUtils.isEmpty(filter.listingTitle) && filter.listingTitle.matches(".* \\(\\d+\\)$"))) { //$NON-NLS-1$ if(filterCounter.containsKey(filter) || (!TextUtils.isEmpty(filter.listingTitle) && filter.listingTitle.matches(".* \\(\\d+\\)$"))) { //$NON-NLS-1$
viewHolder.size.setVisibility(View.VISIBLE); viewHolder.size.setVisibility(View.VISIBLE);
String count; String count = "";
if (filterCounts.containsKey(filter)) { if (filterCounter.containsKey(filter)) {
Integer c = filterCounts.get(filter); Integer c = filterCounter.get(filter);
countInt = c; countInt = c;
count = c.toString(); count = c.toString();
} else {
count = filter.listingTitle.substring(filter.listingTitle.lastIndexOf('(') + 1,
filter.listingTitle.length() - 1);
try {
countInt = Integer.parseInt(count);
} catch (NumberFormatException e) {
//
}
} }
if(!count.equals(viewHolder.size.getText())) {
viewHolder.size.setText(count); viewHolder.size.setText(count);
String title;
int listingTitleSplit = filter.listingTitle.lastIndexOf(' ');
if (listingTitleSplit > 0) {
title = filter.listingTitle.substring(0, listingTitleSplit);
} else {
title = filter.listingTitle;
} }
viewHolder.name.setText(title);
} else { } else {
viewHolder.name.setText(filter.listingTitle);
viewHolder.size.setVisibility(View.GONE); viewHolder.size.setVisibility(View.GONE);
countInt = -1; countInt = -1;
} }

@ -27,6 +27,7 @@ import com.todoroo.astrid.tags.TagService;
import com.todoroo.astrid.utility.Constants; import com.todoroo.astrid.utility.Constants;
import org.tasks.Broadcaster; import org.tasks.Broadcaster;
import org.tasks.filters.FilterCounter;
/** /**
* Astrid application dependency injector loads classes in Astrid with the * Astrid application dependency injector loads classes in Astrid with the
@ -86,6 +87,8 @@ public class AstridDependencyInjector extends AbstractDependencyInjector {
injectables.put("broadcaster", Broadcaster.class); injectables.put("broadcaster", Broadcaster.class);
injectables.put("filterCounter", FilterCounter.class);
// these make reference to fields defined above // these make reference to fields defined above
injectables.put("errorReporters", new ErrorReporter[] { injectables.put("errorReporters", new ErrorReporter[] {
new AndroidLogReporter(), new AndroidLogReporter(),

@ -39,6 +39,7 @@ import com.todoroo.astrid.core.PluginServices;
import com.todoroo.astrid.dao.Database; import com.todoroo.astrid.dao.Database;
import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria; import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria;
import com.todoroo.astrid.dao.TagDataDao; import com.todoroo.astrid.dao.TagDataDao;
import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.data.Metadata; import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.data.TagData; import com.todoroo.astrid.data.TagData;
import com.todoroo.astrid.data.Task; import com.todoroo.astrid.data.Task;
@ -51,6 +52,7 @@ import com.todoroo.astrid.utility.AstridPreferences;
import com.todoroo.astrid.utility.Constants; import com.todoroo.astrid.utility.Constants;
import org.tasks.R; import org.tasks.R;
import org.tasks.filters.FilterCounter;
import java.io.File; import java.io.File;
import java.util.List; import java.util.List;

@ -6,6 +6,7 @@
package com.todoroo.astrid.service; package com.todoroo.astrid.service;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Intent;
import com.todoroo.andlib.data.Property; import com.todoroo.andlib.data.Property;
import com.todoroo.andlib.data.TodorooCursor; import com.todoroo.andlib.data.TodorooCursor;
@ -19,7 +20,7 @@ import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.andlib.utility.DateUtilities; import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.actfm.sync.ActFmPreferenceService; import com.todoroo.astrid.actfm.sync.ActFmPreferenceService;
import com.todoroo.astrid.adapter.UpdateAdapter; import com.todoroo.astrid.adapter.UpdateAdapter;
import com.todoroo.astrid.api.Filter; import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.api.PermaSql; import com.todoroo.astrid.api.PermaSql;
import com.todoroo.astrid.core.PluginServices; import com.todoroo.astrid.core.PluginServices;
import com.todoroo.astrid.dao.MetadataDao; import com.todoroo.astrid.dao.MetadataDao;
@ -38,6 +39,9 @@ import com.todoroo.astrid.tags.TagService;
import com.todoroo.astrid.tags.TaskToTagMetadata; import com.todoroo.astrid.tags.TaskToTagMetadata;
import com.todoroo.astrid.utility.TitleParser; import com.todoroo.astrid.utility.TitleParser;
import org.tasks.Broadcaster;
import org.tasks.filters.FilterCounter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map.Entry; import java.util.Map.Entry;
@ -72,6 +76,12 @@ public class TaskService {
@Autowired @Autowired
private UserActivityDao userActivityDao; private UserActivityDao userActivityDao;
@Autowired
private Broadcaster broadcaster;
@Autowired
private FilterCounter filterCounter;
public TaskService() { public TaskService() {
DependencyInjectionService.getInstance().inject(this); DependencyInjectionService.getInstance().inject(this);
} }
@ -102,7 +112,7 @@ public class TaskService {
item.setCompletionDate(0L); item.setCompletionDate(0L);
} }
taskDao.save(item); save(item);
} }
/** /**
@ -110,6 +120,11 @@ public class TaskService {
*/ */
public void save(Task item) { public void save(Task item) {
taskDao.save(item); taskDao.save(item);
broadcastFilterListUpdated();
}
private void saveWithoutPublishingFilterUpdate(Task item) {
taskDao.save(item);
} }
/** /**
@ -130,7 +145,7 @@ public class TaskService {
if(cursor.getCount() > 0) { if(cursor.getCount() > 0) {
Metadata metadata = new Metadata(); Metadata metadata = new Metadata();
newTask.putTransitory(SyncFlags.GTASKS_SUPPRESS_SYNC, true); newTask.putTransitory(SyncFlags.GTASKS_SUPPRESS_SYNC, true);
taskDao.save(newTask); save(newTask);
long newId = newTask.getId(); long newId = newTask.getId();
for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
metadata.readFromCursor(cursor); metadata.readFromCursor(cursor);
@ -172,7 +187,7 @@ public class TaskService {
item.setId(id); item.setId(id);
GCalHelper.deleteTaskEvent(item); GCalHelper.deleteTaskEvent(item);
item.setDeletionDate(DateUtilities.now()); item.setDeletionDate(DateUtilities.now());
taskDao.save(item); save(item);
} }
} }
@ -265,7 +280,7 @@ public class TaskService {
try { try {
for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
taskValues.setID(cursor.get(Task.ID)); taskValues.setID(cursor.get(Task.ID));
taskDao.save(taskValues); save(taskValues);
} }
return cursor.getCount(); return cursor.getCount();
} finally { } finally {
@ -302,18 +317,6 @@ public class TaskService {
} }
} }
/** count tasks in a given filter */
public int countTasks(Filter filter) {
String queryTemplate = PermaSql.replacePlaceholders(filter.getSqlQuery());
TodorooCursor<Task> cursor = query(Query.select(Task.ID).withQueryTemplate(
queryTemplate));
try {
return cursor.getCount();
} finally {
cursor.close();
}
}
/** /**
* Delete all tasks matching a given criterion * Delete all tasks matching a given criterion
*/ */
@ -329,10 +332,20 @@ public class TaskService {
* <li>!4 - set priority to !!!! * <li>!4 - set priority to !!!!
*/ */
private void quickAdd(Task task, List<String> tags) { private void quickAdd(Task task, List<String> tags) {
save(task); saveWithoutPublishingFilterUpdate(task);
for(String tag : tags) { for(String tag : tags) {
TagService.getInstance().createLink(task, tag); TagService.getInstance().createLink(task, tag);
} }
broadcastFilterListUpdated();
}
private void broadcastFilterListUpdated() {
filterCounter.refreshFilterCounts(new Runnable() {
@Override
public void run() {
broadcaster.sendOrderedBroadcast(new Intent(AstridApiConstants.BROADCAST_EVENT_FILTER_LIST_UPDATED));
}
});
} }
/** /**

@ -0,0 +1,81 @@
package org.tasks.filters;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.sql.Query;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.FilterListItem;
import com.todoroo.astrid.api.PermaSql;
import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.data.Task;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class FilterCounter {
// Previous solution involved a queue of filters and a filterSizeLoadingThread. The filterSizeLoadingThread had
// a few problems: how to make sure that the thread is resumed when the controlling activity is resumed, and
// how to make sure that the the filterQueue does not accumulate filters without being processed. I am replacing
// both the queue and a the thread with a thread pool, which will shut itself off after a second if it has
// nothing to do (corePoolSize == 0, which makes it available for garbage collection), and will wake itself up
// if new filters are queued (obviously it cannot be garbage collected if it is possible for new filters to
// be added).
private final ExecutorService executorService;
private final Map<Filter, Integer> filterCounts = new ConcurrentHashMap<>();
@Autowired
private TaskDao taskDao;
public FilterCounter() {
this(new ThreadPoolExecutor(0, 1, 1, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()));
}
FilterCounter(ExecutorService executorService) {
this.executorService = executorService;
DependencyInjectionService.getInstance().inject(this);
}
public void refreshFilterCounts(final Runnable onComplete) {
executorService.submit(new Runnable() {
@Override
public void run() {
for (Filter filter : filterCounts.keySet()) {
int size = countTasks(filter);
filterCounts.put(filter, size);
}
if (onComplete != null) {
onComplete.run();
}
}
});
}
public void registerFilter(Filter filter) {
filterCounts.put(filter, 0);
}
public boolean containsKey(FilterListItem filter) {
return filterCounts.containsKey(filter);
}
public Integer get(FilterListItem filter) {
return filterCounts.get(filter);
}
private int countTasks(Filter filter) {
String queryTemplate = PermaSql.replacePlaceholders(filter.getSqlQuery());
TodorooCursor<Task> cursor = taskDao.query(
Query.select(Task.ID).withQueryTemplate(queryTemplate));
try {
return cursor.getCount();
} finally {
cursor.close();
}
}
}
Loading…
Cancel
Save