Handle message sets in a single EmailAsyncTask

* This prevents the possibility of RejectedExecutionException when
  selecting large numbers of items

Change-Id: I8f9ba287d69021fdb99b4a8a30cc79755f669b97
This commit is contained in:
Marc Blank 2011-07-16 15:58:38 -07:00
parent eb642812bf
commit b81a31b29b
3 changed files with 72 additions and 63 deletions

View File

@ -24,7 +24,6 @@ import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteCallbackList;
@ -857,10 +856,25 @@ public class Controller {
*
* @param messageId the message to update
* @param isRead the new value for the isRead flag
* @return the AsyncTask that will execute the changes (for testing only)
*/
public AsyncTask<Void, Void, Void> setMessageRead(final long messageId, final boolean isRead) {
return setMessageBoolean(messageId, EmailContent.MessageColumns.FLAG_READ, isRead);
public void setMessageReadSync(long messageId, boolean isRead) {
setMessageBooleanSync(messageId, EmailContent.MessageColumns.FLAG_READ, isRead);
}
/**
* Set/clear the unread status of a message from UI thread
*
* @param messageId the message to update
* @param isRead the new value for the isRead flag
* @return the EmailAsyncTask created
*/
public EmailAsyncTask<Void, Void, Void> setMessageRead(final long messageId,
final boolean isRead) {
return EmailAsyncTask.runAsyncParallel(new Runnable() {
@Override
public void run() {
setMessageBooleanSync(messageId, EmailContent.MessageColumns.FLAG_READ, isRead);
}});
}
/**
@ -903,16 +917,30 @@ public class Controller {
});
}
/**
* Set/clear the favorite status of a message from UI thread
*
* @param messageId the message to update
* @param isFavorite the new value for the isFavorite flag
* @return the EmailAsyncTask created
*/
public EmailAsyncTask<Void, Void, Void> setMessageFavorite(final long messageId,
final boolean isFavorite) {
return EmailAsyncTask.runAsyncParallel(new Runnable() {
@Override
public void run() {
setMessageBooleanSync(messageId, EmailContent.MessageColumns.FLAG_FAVORITE,
isFavorite);
}});
}
/**
* Set/clear the favorite status of a message
*
* @param messageId the message to update
* @param isFavorite the new value for the isFavorite flag
* @return the AsyncTask that will execute the changes (for testing only)
*/
public AsyncTask<Void, Void, Void> setMessageFavorite(final long messageId,
final boolean isFavorite) {
return setMessageBoolean(messageId, EmailContent.MessageColumns.FLAG_FAVORITE, isFavorite);
public void setMessageFavoriteSync(long messageId, boolean isFavorite) {
setMessageBooleanSync(messageId, EmailContent.MessageColumns.FLAG_FAVORITE, isFavorite);
}
/**
@ -921,19 +949,14 @@ public class Controller {
* @param messageId the message to update
* @param columnName the column to update
* @param columnValue the new value for the column
* @return the AsyncTask that will execute the changes (for testing only)
*/
private AsyncTask<Void, Void, Void> setMessageBoolean(final long messageId,
final String columnName, final boolean columnValue) {
return Utility.runAsync(new Runnable() {
public void run() {
ContentValues cv = new ContentValues();
cv.put(columnName, columnValue);
updateMessageSync(messageId, cv);
}
});
private void setMessageBooleanSync(long messageId, String columnName, boolean columnValue) {
ContentValues cv = new ContentValues();
cv.put(columnName, columnValue);
updateMessageSync(messageId, cv);
}
private static final HashMap<Long, SearchParams> sSearchParamsMap =
new HashMap<Long, SearchParams>();

View File

@ -857,17 +857,9 @@ public class MessageListFragment extends ListFragment
}
}
private void onSetMessageRead(long messageId, boolean newRead) {
mController.setMessageRead(messageId, newRead);
}
private void onSetMessageFavorite(long messageId, boolean newFavorite) {
mController.setMessageFavorite(messageId, newFavorite);
}
/**
* Toggles a set read/unread states. Note, the default behavior is "mark unread", so the
* sense of the helper methods is "true=unread".
* sense of the helper methods is "true=unread"; this may be called from the UI thread
*
* @param selectedSet The current list of selected items
*/
@ -880,19 +872,17 @@ public class MessageListFragment extends ListFragment
}
@Override
public boolean setField(long messageId, Cursor c, boolean newValue) {
public void setField(long messageId, Cursor c, boolean newValue) {
boolean oldValue = getField(messageId, c);
if (oldValue != newValue) {
onSetMessageRead(messageId, !newValue);
return true;
}
return false;
mController.setMessageReadSync(messageId, !newValue);
}
}
});
}
/**
* Toggles a set of favorites (stars)
* Toggles a set of favorites (stars); this may be called from the UI thread
*
* @param selectedSet The current list of selected items
*/
@ -905,14 +895,12 @@ public class MessageListFragment extends ListFragment
}
@Override
public boolean setField(long messageId, Cursor c, boolean newValue) {
public void setField(long messageId, Cursor c, boolean newValue) {
boolean oldValue = getField(messageId, c);
if (oldValue != newValue) {
onSetMessageFavorite(messageId, newValue);
return true;
mController.setMessageFavoriteSync(messageId, newValue);
}
return false;
}
}
});
}
@ -936,25 +924,25 @@ public class MessageListFragment extends ListFragment
public boolean getField(long messageId, Cursor c);
/**
* Set or clear the field of interest. Return true if a change was made.
* Set or clear the field of interest; setField is called asynchronously via EmailAsyncTask
* @param messageId the message id of the current message
* @param c the cursor, positioned to the item of interest
* @param newValue the new value to be set at this row
* @return true if a change was actually made
*/
public boolean setField(long messageId, Cursor c, boolean newValue);
public void setField(long messageId, Cursor c, boolean newValue);
}
/**
* Toggle multiple fields in a message, using the following logic: If one or more fields
* are "clear", then "set" them. If all fields are "set", then "clear" them all.
* are "clear", then "set" them. If all fields are "set", then "clear" them all. Provider
* calls are applied asynchronously in setField
*
* @param selectedSet the set of messages that are selected
* @param helper functions to implement the specific getter & setter
* @return the number of messages that were updated
*/
private int toggleMultiple(Set<Long> selectedSet, MultiToggleHelper helper) {
Cursor c = mListAdapter.getCursor();
private void toggleMultiple(final Set<Long> selectedSet, final MultiToggleHelper helper) {
final Cursor c = mListAdapter.getCursor();
boolean anyWereFound = false;
boolean allWereSet = true;
@ -970,22 +958,20 @@ public class MessageListFragment extends ListFragment
}
}
int numChanged = 0;
if (anyWereFound) {
boolean newValue = !allWereSet;
final boolean newValue = !allWereSet;
c.moveToPosition(-1);
while (c.moveToNext()) {
long id = c.getInt(MessagesAdapter.COLUMN_ID);
if (selectedSet.contains(Long.valueOf(id))) {
if (helper.setField(id, c, newValue)) {
++numChanged;
EmailAsyncTask.runAsyncParallel(new Runnable() {
@Override
public void run() {
while (c.moveToNext()) {
long id = c.getInt(MessagesAdapter.COLUMN_ID);
if (selectedSet.contains(Long.valueOf(id))) {
helper.setField(id, c, newValue);
}
}
}
}
}});
}
return numChanged;
}
/**
@ -1048,13 +1034,13 @@ public class MessageListFragment extends ListFragment
/** Implements {@link MessagesAdapter.Callback} */
@Override
public void onAdapterFavoriteChanged(MessageListItem itemView, boolean newFavorite) {
onSetMessageFavorite(itemView.mMessageId, newFavorite);
mController.setMessageFavorite(itemView.mMessageId, newFavorite);
}
/** Implements {@link MessagesAdapter.Callback} */
@Override
public void onAdapterSelectedChanged(
MessageListItem itemView, boolean newSelected, int mSelectedCount) {
public void onAdapterSelectedChanged(MessageListItem itemView, boolean newSelected,
int mSelectedCount) {
updateSelectionMode();
}

View File

@ -16,6 +16,10 @@
package com.android.email;
import android.content.Context;
import android.net.Uri;
import android.test.ProviderTestCase2;
import com.android.email.provider.ContentCache;
import com.android.email.provider.EmailProvider;
import com.android.email.provider.ProviderTestUtils;
@ -26,10 +30,6 @@ import com.android.emailcommon.provider.EmailContent.Message;
import com.android.emailcommon.provider.HostAuth;
import com.android.emailcommon.provider.Mailbox;
import android.content.Context;
import android.net.Uri;
import android.test.ProviderTestCase2;
import java.util.Locale;
import java.util.concurrent.ExecutionException;