Improve EmailAsyncTask
Added 6 methods: - execute{Parallel,Serial} - cancelPreviousAndExecute{Parallel,Serial} - runAsyncParallel{Parallel,Serial} (replacement for Utility.runAsync) Bug 4083415 Change-Id: I5ca33000e52fc5265ccc84a6e5acb0d3359d0eb4
This commit is contained in:
parent
ad93ba9f1c
commit
d72f7bdf11
@ -18,14 +18,16 @@ package com.android.emailcommon.utility;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* {@link AsyncTask} substitution for the email app.
|
||||
*
|
||||
* Modeled after {@link AsyncTask}; the basic usage is the same, with extra features:
|
||||
* - Bulk cancellation of multiple tasks. This is mainly used by UI to cancell pending tasks
|
||||
* - Bulk cancellation of multiple tasks. This is mainly used by UI to cancel pending tasks
|
||||
* in onDestroy() or similar places.
|
||||
* - More features to come...
|
||||
*
|
||||
@ -33,6 +35,9 @@ import java.util.concurrent.ExecutionException;
|
||||
* {@link AsyncTask#onProgressUpdate}. Add these when necessary.
|
||||
*/
|
||||
public abstract class EmailAsyncTask<Params, Progress, Result> {
|
||||
private static final Executor SERIAL_EXECUTOR = AsyncTask.SERIAL_EXECUTOR;
|
||||
private static final Executor PARALLEL_EXECUTOR = AsyncTask.THREAD_POOL_EXECUTOR;
|
||||
|
||||
/**
|
||||
* Tracks {@link EmailAsyncTask}.
|
||||
*
|
||||
@ -66,9 +71,34 @@ public abstract class EmailAsyncTask<Params, Progress, Result> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel all instances of the same class as {@code current} other than
|
||||
* {@code current} itself.
|
||||
*/
|
||||
/* package */ void cancelOthers(EmailAsyncTask<?, ?, ?> current) {
|
||||
final Class<?> clazz = current.getClass();
|
||||
synchronized (mTasks) {
|
||||
final ArrayList<EmailAsyncTask<?, ?, ?>> toRemove =
|
||||
new ArrayList<EmailAsyncTask<?, ?, ?>>();
|
||||
for (EmailAsyncTask<?, ?, ?> task : mTasks) {
|
||||
if ((task != current) && task.getClass().equals(clazz)) {
|
||||
task.cancel(true);
|
||||
toRemove.add(task);
|
||||
}
|
||||
}
|
||||
for (EmailAsyncTask<?, ?, ?> task : toRemove) {
|
||||
mTasks.remove(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* package */ int getTaskCountForTest() {
|
||||
return mTasks.size();
|
||||
}
|
||||
|
||||
/* package */ boolean containsTaskForTest(EmailAsyncTask<?, ?, ?> task) {
|
||||
return mTasks.contains(task);
|
||||
}
|
||||
}
|
||||
|
||||
private final Tracker mTracker;
|
||||
@ -109,46 +139,127 @@ public abstract class EmailAsyncTask<Params, Progress, Result> {
|
||||
mInnerTask = new InnerTask<Params, Progress, Result>(this);
|
||||
}
|
||||
|
||||
/* package */ void unregisterSelf() {
|
||||
/* package */ final void unregisterSelf() {
|
||||
if (mTracker != null) {
|
||||
mTracker.remove(this);
|
||||
}
|
||||
}
|
||||
|
||||
/** @see AsyncTask#doInBackground */
|
||||
protected abstract Result doInBackground(Params... params);
|
||||
|
||||
|
||||
/** @see AsyncTask#cancel(boolean) */
|
||||
public final boolean cancel(boolean mayInterruptIfRunning) {
|
||||
return mInnerTask.cancel(mayInterruptIfRunning);
|
||||
}
|
||||
|
||||
/** @see AsyncTask#onCancelled */
|
||||
protected void onCancelled(Result result) {
|
||||
}
|
||||
|
||||
/** @see AsyncTask#onPostExecute */
|
||||
protected void onPostExecute(Result result) {
|
||||
}
|
||||
|
||||
public final EmailAsyncTask<Params, Progress, Result> execute(Params... params) {
|
||||
mInnerTask.execute(params);
|
||||
/**
|
||||
* execute on {@link #PARALLEL_EXECUTOR}
|
||||
*
|
||||
* @see AsyncTask#execute
|
||||
*/
|
||||
public final EmailAsyncTask<Params, Progress, Result> executeParallel(Params... params) {
|
||||
return executeInternal(PARALLEL_EXECUTOR, false, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* execute on {@link #SERIAL_EXECUTOR}
|
||||
*
|
||||
* @see AsyncTask#execute
|
||||
*/
|
||||
public final EmailAsyncTask<Params, Progress, Result> executeSerial(Params... params) {
|
||||
return executeInternal(SERIAL_EXECUTOR, false, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel all previously created instances of the same class tracked by the same
|
||||
* {@link Tracker}, and then {@link #executeParallel}.
|
||||
*/
|
||||
public final EmailAsyncTask<Params, Progress, Result> cancelPreviousAndExecuteParallel(
|
||||
Params... params) {
|
||||
return executeInternal(PARALLEL_EXECUTOR, true, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel all previously created instances of the same class tracked by the same
|
||||
* {@link Tracker}, and then {@link #executeSerial}.
|
||||
*/
|
||||
public final EmailAsyncTask<Params, Progress, Result> cancelPreviousAndExecuteSerial(
|
||||
Params... params) {
|
||||
return executeInternal(SERIAL_EXECUTOR, true, params);
|
||||
}
|
||||
|
||||
private final EmailAsyncTask<Params, Progress, Result> executeInternal(Executor executor,
|
||||
boolean cancelPrevious, Params... params) {
|
||||
if (cancelPrevious) {
|
||||
if (mTracker == null) {
|
||||
throw new IllegalStateException();
|
||||
} else {
|
||||
mTracker.cancelOthers(this);
|
||||
}
|
||||
}
|
||||
mInnerTask.executeOnExecutor(executor, params);
|
||||
return this;
|
||||
}
|
||||
|
||||
public final Result get() throws InterruptedException, ExecutionException {
|
||||
return mInnerTask.get();
|
||||
/**
|
||||
* Runs a {@link Runnable} in a bg thread, using {@link #PARALLEL_EXECUTOR}.
|
||||
*/
|
||||
public static EmailAsyncTask<Void, Void, Void> runAsyncParallel(Runnable runnable) {
|
||||
return runAsyncInternal(PARALLEL_EXECUTOR, runnable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a {@link Runnable} in a bg thread, using {@link #SERIAL_EXECUTOR}.
|
||||
*/
|
||||
public static EmailAsyncTask<Void, Void, Void> runAsyncSerial(Runnable runnable) {
|
||||
return runAsyncInternal(SERIAL_EXECUTOR, runnable);
|
||||
}
|
||||
|
||||
private static EmailAsyncTask<Void, Void, Void> runAsyncInternal(Executor executor,
|
||||
final Runnable runnable) {
|
||||
EmailAsyncTask<Void, Void, Void> task = new EmailAsyncTask<Void, Void, Void>(null) {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
runnable.run();
|
||||
return null;
|
||||
}
|
||||
};
|
||||
return task.executeInternal(executor, false, (Void[]) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait until {@link #doInBackground} finishes.
|
||||
*
|
||||
* @see AsyncTask#get
|
||||
*/
|
||||
public final void waitForFinish() throws InterruptedException, ExecutionException {
|
||||
mInnerTask.get();
|
||||
}
|
||||
|
||||
/** @see AsyncTask#isCancelled */
|
||||
public final boolean isCancelled() {
|
||||
return mInnerTask.isCancelled();
|
||||
}
|
||||
|
||||
/* package */ Result callDoInBackgroundForTest(Params... params) {
|
||||
/* package */ final Result callDoInBackgroundForTest(Params... params) {
|
||||
return mInnerTask.doInBackground(params);
|
||||
}
|
||||
|
||||
/* package */ void callOnCancelledForTest(Result result) {
|
||||
/* package */ final void callOnCancelledForTest(Result result) {
|
||||
mInnerTask.onCancelled(result);
|
||||
}
|
||||
|
||||
/* package */ void callOnPostExecuteForTest(Result result) {
|
||||
/* package */ final void callOnPostExecuteForTest(Result result) {
|
||||
mInnerTask.onPostExecute(result);
|
||||
}
|
||||
}
|
||||
|
@ -573,14 +573,18 @@ public class Utility {
|
||||
* Run {@code r} on a worker thread, returning the AsyncTask
|
||||
* @return the AsyncTask; this is primarily for use by unit tests, which require the
|
||||
* result of the task
|
||||
*
|
||||
* @deprecated use {@link EmailAsyncTask#runAsyncParallel} or
|
||||
* {@link EmailAsyncTask#runAsyncSerial}
|
||||
*/
|
||||
@Deprecated
|
||||
public static AsyncTask<Void, Void, Void> runAsync(final Runnable r) {
|
||||
return new AsyncTask<Void, Void, Void>() {
|
||||
@Override protected Void doInBackground(Void... params) {
|
||||
r.run();
|
||||
return null;
|
||||
}
|
||||
}.execute();
|
||||
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -19,12 +19,11 @@ package com.android.email.activity;
|
||||
import com.android.email.R;
|
||||
import com.android.emailcommon.provider.EmailContent;
|
||||
import com.android.emailcommon.provider.EmailContent.Account;
|
||||
import com.android.emailcommon.utility.Utility;
|
||||
import com.android.emailcommon.utility.EmailAsyncTask;
|
||||
|
||||
import android.app.ListActivity;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.view.View;
|
||||
@ -43,7 +42,7 @@ import android.widget.SimpleCursorAdapter;
|
||||
public class AccountShortcutPicker extends ListActivity
|
||||
implements OnClickListener, OnItemClickListener {
|
||||
|
||||
private AccountTask mAccountTask;
|
||||
private final EmailAsyncTask.Tracker mTaskTracker = new EmailAsyncTask.Tracker();
|
||||
|
||||
/**
|
||||
* Support for list adapter
|
||||
@ -74,16 +73,14 @@ public class AccountShortcutPicker extends ListActivity
|
||||
listView.setOnItemClickListener(this);
|
||||
listView.setItemsCanFocus(false);
|
||||
|
||||
mAccountTask = new AccountTask();
|
||||
mAccountTask.execute();
|
||||
new AccountTask().executeParallel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
// Cleanup running async task (if any)
|
||||
Utility.cancelTaskInterrupt(mAccountTask);
|
||||
mAccountTask = null;
|
||||
mTaskTracker.cancellAllInterrupt();
|
||||
// Cleanup accounts cursor (if any)
|
||||
SimpleCursorAdapter adapter = (SimpleCursorAdapter) getListAdapter();
|
||||
if (adapter != null) {
|
||||
@ -114,7 +111,10 @@ public class AccountShortcutPicker extends ListActivity
|
||||
/**
|
||||
* Load the accounts and create the adapter.
|
||||
*/
|
||||
private class AccountTask extends AsyncTask<Void, Void, Cursor> {
|
||||
private class AccountTask extends EmailAsyncTask<Void, Void, Cursor> {
|
||||
public AccountTask() {
|
||||
super(mTaskTracker);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Cursor doInBackground(Void... params) {
|
||||
|
@ -34,6 +34,7 @@ import com.android.emailcommon.provider.EmailContent.BodyColumns;
|
||||
import com.android.emailcommon.provider.EmailContent.Message;
|
||||
import com.android.emailcommon.provider.EmailContent.MessageColumns;
|
||||
import com.android.emailcommon.utility.AttachmentUtilities;
|
||||
import com.android.emailcommon.utility.EmailAsyncTask;
|
||||
import com.android.emailcommon.utility.Utility;
|
||||
|
||||
import android.app.ActionBar;
|
||||
@ -48,7 +49,6 @@ import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.provider.OpenableColumns;
|
||||
@ -157,8 +157,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
||||
private Controller mController;
|
||||
private boolean mDraftNeedsSaving;
|
||||
private boolean mMessageLoaded;
|
||||
private AsyncTask<Long, Void, Attachment[]> mLoadAttachmentsTask;
|
||||
private AsyncTask<Void, Void, Object[]> mLoadMessageTask;
|
||||
private final EmailAsyncTask.Tracker mTaskTracker = new EmailAsyncTask.Tracker();
|
||||
|
||||
private EmailAddressAdapter mAddressAdapterTo;
|
||||
private EmailAddressAdapter mAddressAdapterCc;
|
||||
@ -336,7 +335,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
||||
// Otherwise, handle the internal cases (Message Composer invoked from within app)
|
||||
long messageId = draftId != -1 ? draftId : intent.getLongExtra(EXTRA_MESSAGE_ID, -1);
|
||||
if (messageId != -1) {
|
||||
mLoadMessageTask = new LoadMessageTask(messageId).execute();
|
||||
new LoadMessageTask(messageId).executeParallel();
|
||||
} else {
|
||||
setAccount(intent);
|
||||
// Since this is a new message, we don't need to call LoadMessageTask.
|
||||
@ -394,10 +393,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
||||
mQuotedText.destroy();
|
||||
mQuotedText = null;
|
||||
|
||||
Utility.cancelTaskInterrupt(mLoadAttachmentsTask);
|
||||
mLoadAttachmentsTask = null;
|
||||
Utility.cancelTaskInterrupt(mLoadMessageTask);
|
||||
mLoadMessageTask = null;
|
||||
mTaskTracker.cancellAllInterrupt();
|
||||
|
||||
if (mAddressAdapterTo != null) {
|
||||
mAddressAdapterTo.close();
|
||||
@ -608,10 +604,11 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
||||
mAddressAdapterBcc = new EmailAddressAdapter(this);
|
||||
}
|
||||
|
||||
private class LoadMessageTask extends AsyncTask<Void, Void, Object[]> {
|
||||
private class LoadMessageTask extends EmailAsyncTask<Void, Void, Object[]> {
|
||||
private final long mMessageId;
|
||||
|
||||
public LoadMessageTask(long messageId) {
|
||||
super(mTaskTracker);
|
||||
mMessageId = messageId;
|
||||
}
|
||||
|
||||
@ -686,7 +683,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
||||
} else {
|
||||
mSource = message;
|
||||
}
|
||||
mLoadAttachmentsTask = new AsyncTask<Long, Void, Attachment[]>() {
|
||||
new EmailAsyncTask<Long, Void, Attachment[]>(mTaskTracker) {
|
||||
@Override
|
||||
protected Attachment[] doInBackground(Long... messageIds) {
|
||||
return Attachment.restoreAttachmentsWithMessageId(MessageCompose.this,
|
||||
@ -716,7 +713,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
||||
addAttachment(attachment, allowDelete);
|
||||
}
|
||||
}
|
||||
}.execute(message.mId);
|
||||
}.executeParallel(message.mId);
|
||||
} else if (ACTION_REPLY.equals(mAction) || ACTION_REPLY_ALL.equals(mAction)) {
|
||||
mSource = message;
|
||||
} else if (Email.LOGD) {
|
||||
@ -909,10 +906,11 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
||||
}
|
||||
}
|
||||
|
||||
private class SendOrSaveMessageTask extends AsyncTask<Void, Void, Void> {
|
||||
private class SendOrSaveMessageTask extends EmailAsyncTask<Void, Void, Void> {
|
||||
private final boolean mSend;
|
||||
|
||||
public SendOrSaveMessageTask(boolean send) {
|
||||
super(null /* DO NOT cancel in onDestroy */);
|
||||
if (send && ActivityManager.isUserAMonkey()) {
|
||||
Log.d(Logging.LOG_TAG, "Inhibiting send while monkey is in charge.");
|
||||
send = false;
|
||||
@ -994,9 +992,6 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
||||
sSaveInProgress = false;
|
||||
sSaveInProgressCondition.notify();
|
||||
}
|
||||
if (isCancelled()) {
|
||||
return;
|
||||
}
|
||||
// Don't display the toast if the user is just changing the orientation
|
||||
if (!mSend && (getChangingConfigurations() & ActivityInfo.CONFIG_ORIENTATION) == 0) {
|
||||
Toast.makeText(MessageCompose.this, R.string.message_saved_toast,
|
||||
@ -1020,7 +1015,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
||||
synchronized (sSaveInProgressCondition) {
|
||||
sSaveInProgress = true;
|
||||
}
|
||||
new SendOrSaveMessageTask(send).execute();
|
||||
new SendOrSaveMessageTask(send).executeParallel();
|
||||
}
|
||||
|
||||
private void saveIfNeeded() {
|
||||
@ -1252,16 +1247,13 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
|
||||
mAttachments.removeView(attachmentView);
|
||||
updateAttachmentContainer();
|
||||
if (attachment.mMessageKey == mDraft.mId && attachment.isSaved()) {
|
||||
// The following async task for deleting attachments:
|
||||
// - can be started multiple times in parallel (to delete multiple attachments).
|
||||
// - need not be interrupted on activity exit, instead should run to completion.
|
||||
new AsyncTask<Long, Void, Void>() {
|
||||
final long attachmentId = attachment.mId;
|
||||
EmailAsyncTask.runAsyncParallel(new Runnable() {
|
||||
@Override
|
||||
protected Void doInBackground(Long... attachmentIds) {
|
||||
mController.deleteAttachment(attachmentIds[0]);
|
||||
return null;
|
||||
public void run() {
|
||||
mController.deleteAttachment(attachmentId);
|
||||
}
|
||||
}.execute(attachment.mId);
|
||||
});
|
||||
}
|
||||
setDraftNeedsSaving(true);
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ import com.android.emailcommon.provider.EmailContent;
|
||||
import com.android.emailcommon.provider.EmailContent.Account;
|
||||
import com.android.emailcommon.provider.EmailContent.Mailbox;
|
||||
import com.android.emailcommon.provider.EmailContent.Message;
|
||||
import com.android.emailcommon.utility.EmailAsyncTask;
|
||||
import com.android.emailcommon.utility.Utility;
|
||||
import com.android.emailcommon.utility.Utility.ListStateSaver;
|
||||
|
||||
@ -42,13 +43,11 @@ import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
@ -160,7 +159,7 @@ public class MessageListFragment extends ListFragment
|
||||
|
||||
private Utility.ListStateSaver mSavedListState;
|
||||
|
||||
private MessageOpenTask mMessageOpenTask;
|
||||
private final EmailAsyncTask.Tracker mTaskTracker = new EmailAsyncTask.Tracker();
|
||||
|
||||
/**
|
||||
* Callback interface that owning activities must implement
|
||||
@ -306,8 +305,7 @@ public class MessageListFragment extends ListFragment
|
||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
Log.d(Logging.LOG_TAG, "MessageListFragment onDestroy");
|
||||
}
|
||||
Utility.cancelTaskInterrupt(mMessageOpenTask);
|
||||
mMessageOpenTask = null;
|
||||
mTaskTracker.cancellAllInterrupt();
|
||||
mRefreshManager.unregisterListener(mRefreshListener);
|
||||
super.onDestroy();
|
||||
}
|
||||
@ -637,19 +635,18 @@ public class MessageListFragment extends ListFragment
|
||||
* @param messageId ID of the msesage to open.
|
||||
*/
|
||||
private void onMessageOpen(final long messageMailboxId, final long messageId) {
|
||||
Utility.cancelTaskInterrupt(mMessageOpenTask);
|
||||
mMessageOpenTask = new MessageOpenTask(messageMailboxId, messageId);
|
||||
mMessageOpenTask.execute();
|
||||
new MessageOpenTask(messageMailboxId, messageId).cancelPreviousAndExecuteParallel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Task to look up the mailbox type for a message, and kicks the callback.
|
||||
*/
|
||||
private class MessageOpenTask extends AsyncTask<Void, Void, Integer> {
|
||||
private class MessageOpenTask extends EmailAsyncTask<Void, Void, Integer> {
|
||||
private final long mMessageMailboxId;
|
||||
private final long mMessageId;
|
||||
|
||||
public MessageOpenTask(long messageMailboxId, long messageId) {
|
||||
super(mTaskTracker);
|
||||
mMessageMailboxId = messageMailboxId;
|
||||
mMessageId = messageId;
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ import com.android.emailcommon.Logging;
|
||||
import com.android.emailcommon.mail.MessagingException;
|
||||
import com.android.emailcommon.provider.EmailContent.Account;
|
||||
import com.android.emailcommon.provider.EmailContent.Mailbox;
|
||||
import com.android.emailcommon.utility.EmailAsyncTask;
|
||||
import com.android.emailcommon.utility.Utility;
|
||||
|
||||
import android.app.ActionBar;
|
||||
@ -39,7 +40,6 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.Loader;
|
||||
import android.database.Cursor;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.text.TextUtils;
|
||||
@ -88,7 +88,7 @@ public class MessageListXL extends Activity implements
|
||||
private final MessageOrderManagerCallback mMessageOrderManagerCallback
|
||||
= new MessageOrderManagerCallback();
|
||||
|
||||
private RefreshTask mRefreshTask;
|
||||
private final EmailAsyncTask.Tracker mTaskTracker = new EmailAsyncTask.Tracker();
|
||||
|
||||
private BannerController mBannerController;
|
||||
private TextView mErrorMessageView;
|
||||
@ -264,7 +264,7 @@ public class MessageListXL extends Activity implements
|
||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) Log.d(Logging.LOG_TAG, "MessageListXL onDestroy");
|
||||
mIsCreated = false;
|
||||
mController.removeResultCallback(mControllerResult);
|
||||
Utility.cancelTaskInterrupt(mRefreshTask);
|
||||
mTaskTracker.cancellAllInterrupt();
|
||||
mRefreshManager.unregisterListener(mMailRefreshManagerListener);
|
||||
mFragmentManager.onDestroy();
|
||||
super.onDestroy();
|
||||
@ -561,7 +561,7 @@ public class MessageListXL extends Activity implements
|
||||
* Call this when getting a connection error.
|
||||
*/
|
||||
private void showErrorMessage(final String rawMessage, final long accountId) {
|
||||
new AsyncTask<Void, Void, String>() {
|
||||
new EmailAsyncTask<Void, Void, String>(mTaskTracker) {
|
||||
@Override
|
||||
protected String doInBackground(Void... params) {
|
||||
Account account = Account.restoreAccountWithId(MessageListXL.this, accountId);
|
||||
@ -570,9 +570,6 @@ public class MessageListXL extends Activity implements
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(String accountName) {
|
||||
if (!mIsCreated) {
|
||||
return; // activity destroyed.
|
||||
}
|
||||
final String message;
|
||||
if (TextUtils.isEmpty(accountName)) {
|
||||
message = rawMessage;
|
||||
@ -585,8 +582,7 @@ public class MessageListXL extends Activity implements
|
||||
mLastErrorAccountId = accountId;
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
|
||||
}.executeParallel();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -776,10 +772,8 @@ public class MessageListXL extends Activity implements
|
||||
|
||||
private void onRefresh() {
|
||||
// Cancel previously running instance if any.
|
||||
Utility.cancelTaskInterrupt(mRefreshTask);
|
||||
mRefreshTask = new RefreshTask(this, mFragmentManager.getActualAccountId(),
|
||||
mFragmentManager.getMailboxId());
|
||||
mRefreshTask.execute();
|
||||
new RefreshTask(mTaskTracker, this, mFragmentManager.getActualAccountId(),
|
||||
mFragmentManager.getMailboxId()).cancelPreviousAndExecuteParallel();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -795,7 +789,7 @@ public class MessageListXL extends Activity implements
|
||||
* {@link #INBOX_AUTO_REFRESH_MIN_INTERVAL}.
|
||||
* </ul>
|
||||
*/
|
||||
/* package */ static class RefreshTask extends AsyncTask<Void, Void, Boolean> {
|
||||
/* package */ static class RefreshTask extends EmailAsyncTask<Void, Void, Boolean> {
|
||||
private final Clock mClock;
|
||||
private final Context mContext;
|
||||
private final long mAccountId;
|
||||
@ -803,13 +797,15 @@ public class MessageListXL extends Activity implements
|
||||
private final RefreshManager mRefreshManager;
|
||||
/* package */ long mInboxId;
|
||||
|
||||
public RefreshTask(Context context, long accountId, long mailboxId) {
|
||||
this(context, accountId, mailboxId, Clock.INSTANCE,
|
||||
public RefreshTask(EmailAsyncTask.Tracker tracker, Context context, long accountId,
|
||||
long mailboxId) {
|
||||
this(tracker, context, accountId, mailboxId, Clock.INSTANCE,
|
||||
RefreshManager.getInstance(context));
|
||||
}
|
||||
|
||||
/* package */ RefreshTask(Context context, long accountId, long mailboxId, Clock clock,
|
||||
RefreshManager refreshManager) {
|
||||
/* package */ RefreshTask(EmailAsyncTask.Tracker tracker, Context context, long accountId,
|
||||
long mailboxId, Clock clock, RefreshManager refreshManager) {
|
||||
super(tracker);
|
||||
mClock = clock;
|
||||
mContext = context;
|
||||
mRefreshManager = refreshManager;
|
||||
|
@ -56,7 +56,6 @@ import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.media.MediaScannerConnection;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
@ -137,11 +136,6 @@ public abstract class MessageViewFragmentBase extends Fragment implements View.O
|
||||
private long mMessageId = -1;
|
||||
private Message mMessage;
|
||||
|
||||
private LoadMessageTask mLoadMessageTask;
|
||||
private ReloadMessageTask mReloadMessageTask;
|
||||
private LoadBodyTask mLoadBodyTask;
|
||||
private LoadAttachmentsTask mLoadAttachmentsTask;
|
||||
|
||||
private Controller mController;
|
||||
private ControllerResultUiThreadWrapper<ControllerResults> mControllerCallback;
|
||||
|
||||
@ -206,8 +200,7 @@ public abstract class MessageViewFragmentBase extends Fragment implements View.O
|
||||
|
||||
private boolean mRestoredPictureLoaded;
|
||||
|
||||
private final EmailAsyncTask.Tracker mUpdatePreviewIconTaskTracker
|
||||
= new EmailAsyncTask.Tracker();
|
||||
private final EmailAsyncTask.Tracker mTaskTracker = new EmailAsyncTask.Tracker();
|
||||
|
||||
/**
|
||||
* Zoom scales for webview. Values correspond to {@link Preferences#TEXT_ZOOM_TINY}..
|
||||
@ -427,15 +420,7 @@ public abstract class MessageViewFragmentBase extends Fragment implements View.O
|
||||
|
||||
private void cancelAllTasks() {
|
||||
mMessageObserver.unregister();
|
||||
mUpdatePreviewIconTaskTracker.cancellAllInterrupt();
|
||||
Utility.cancelTaskInterrupt(mLoadMessageTask);
|
||||
mLoadMessageTask = null;
|
||||
Utility.cancelTaskInterrupt(mReloadMessageTask);
|
||||
mReloadMessageTask = null;
|
||||
Utility.cancelTaskInterrupt(mLoadBodyTask);
|
||||
mLoadBodyTask = null;
|
||||
Utility.cancelTaskInterrupt(mLoadAttachmentsTask);
|
||||
mLoadAttachmentsTask = null;
|
||||
mTaskTracker.cancellAllInterrupt();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -483,8 +468,7 @@ public abstract class MessageViewFragmentBase extends Fragment implements View.O
|
||||
mLoadWhenResumed = false;
|
||||
cancelAllTasks();
|
||||
resetView();
|
||||
mLoadMessageTask = new LoadMessageTask(true);
|
||||
mLoadMessageTask.execute();
|
||||
new LoadMessageTask(true).executeParallel();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -816,7 +800,7 @@ public abstract class MessageViewFragmentBase extends Fragment implements View.O
|
||||
// assume the download won't start right away, and we make the cancel button visible
|
||||
attachment.cancelButton.setVisibility(View.GONE);
|
||||
// Create the timed task that will change the button state
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
new EmailAsyncTask<Void, Void, Void>(mTaskTracker) {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
try {
|
||||
@ -831,7 +815,7 @@ public abstract class MessageViewFragmentBase extends Fragment implements View.O
|
||||
attachment.cancelButton.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}.executeParallel();
|
||||
} else {
|
||||
attachment.cancelButton.setVisibility(View.VISIBLE);
|
||||
}
|
||||
@ -966,7 +950,7 @@ public abstract class MessageViewFragmentBase extends Fragment implements View.O
|
||||
/**
|
||||
* Async task for loading a single message outside of the UI thread
|
||||
*/
|
||||
private class LoadMessageTask extends AsyncTask<Void, Void, Message> {
|
||||
private class LoadMessageTask extends EmailAsyncTask<Void, Void, Message> {
|
||||
|
||||
private final boolean mOkToFetch;
|
||||
private int mMailboxType;
|
||||
@ -975,6 +959,7 @@ public abstract class MessageViewFragmentBase extends Fragment implements View.O
|
||||
* Special constructor to cache some local info
|
||||
*/
|
||||
public LoadMessageTask(boolean okToFetch) {
|
||||
super(mTaskTracker);
|
||||
mOkToFetch = okToFetch;
|
||||
}
|
||||
|
||||
@ -1015,7 +1000,11 @@ public abstract class MessageViewFragmentBase extends Fragment implements View.O
|
||||
/**
|
||||
* Kicked by {@link MessageObserver}. Reload the message and update the views.
|
||||
*/
|
||||
private class ReloadMessageTask extends AsyncTask<Void, Void, Message> {
|
||||
private class ReloadMessageTask extends EmailAsyncTask<Void, Void, Message> {
|
||||
public ReloadMessageTask() {
|
||||
super(mTaskTracker);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Message doInBackground(Void... params) {
|
||||
if (!isMessageSpecified()) { // just in case
|
||||
@ -1060,7 +1049,7 @@ public abstract class MessageViewFragmentBase extends Fragment implements View.O
|
||||
/**
|
||||
* Async task for loading a single message body outside of the UI thread
|
||||
*/
|
||||
private class LoadBodyTask extends AsyncTask<Void, Void, String[]> {
|
||||
private class LoadBodyTask extends EmailAsyncTask<Void, Void, String[]> {
|
||||
|
||||
private long mId;
|
||||
private boolean mErrorLoadingMessageBody;
|
||||
@ -1069,6 +1058,7 @@ public abstract class MessageViewFragmentBase extends Fragment implements View.O
|
||||
* Special constructor to cache some local info
|
||||
*/
|
||||
public LoadBodyTask(long messageId) {
|
||||
super(mTaskTracker);
|
||||
mId = messageId;
|
||||
}
|
||||
|
||||
@ -1112,7 +1102,11 @@ public abstract class MessageViewFragmentBase extends Fragment implements View.O
|
||||
* this implementation is incomplete, as it will fail to refresh properly if the message is
|
||||
* partially loaded at this time.
|
||||
*/
|
||||
private class LoadAttachmentsTask extends AsyncTask<Long, Void, Attachment[]> {
|
||||
private class LoadAttachmentsTask extends EmailAsyncTask<Long, Void, Attachment[]> {
|
||||
public LoadAttachmentsTask() {
|
||||
super(mTaskTracker);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Attachment[] doInBackground(Long... messageIds) {
|
||||
return Attachment.restoreAttachmentsWithMessageId(mContext, messageIds[0]);
|
||||
@ -1419,8 +1413,7 @@ public abstract class MessageViewFragmentBase extends Fragment implements View.O
|
||||
} else {
|
||||
mControllerCallback.getWrappee().setWaitForLoadMessageId(-1);
|
||||
// Ask for body
|
||||
mLoadBodyTask = new LoadBodyTask(message.mId);
|
||||
mLoadBodyTask.execute();
|
||||
new LoadBodyTask(message.mId).executeParallel();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1560,8 +1553,7 @@ public abstract class MessageViewFragmentBase extends Fragment implements View.O
|
||||
setMessageHtml(text);
|
||||
|
||||
// Ask for attachments after body
|
||||
mLoadAttachmentsTask = new LoadAttachmentsTask();
|
||||
mLoadAttachmentsTask.execute(mMessage.mId);
|
||||
new LoadAttachmentsTask().executeParallel(mMessage.mId);
|
||||
|
||||
mIsMessageLoadedForTest = true;
|
||||
}
|
||||
@ -1626,8 +1618,7 @@ public abstract class MessageViewFragmentBase extends Fragment implements View.O
|
||||
// reload UI and reload everything else too
|
||||
// pass false to LoadMessageTask to prevent looping here
|
||||
cancelAllTasks();
|
||||
mLoadMessageTask = new LoadMessageTask(false);
|
||||
mLoadMessageTask.execute();
|
||||
new LoadMessageTask(false).executeParallel();
|
||||
break;
|
||||
default:
|
||||
// do nothing - we don't have a progress bar at this time
|
||||
@ -1748,14 +1739,12 @@ public abstract class MessageViewFragmentBase extends Fragment implements View.O
|
||||
if (!isMessageSpecified()) {
|
||||
return;
|
||||
}
|
||||
Utility.cancelTaskInterrupt(mReloadMessageTask);
|
||||
mReloadMessageTask = new ReloadMessageTask();
|
||||
mReloadMessageTask.execute();
|
||||
new ReloadMessageTask().cancelPreviousAndExecuteParallel();
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePreviewIcon(MessageViewAttachmentInfo attachmentInfo) {
|
||||
new UpdatePreviewIconTask(attachmentInfo).execute();
|
||||
new UpdatePreviewIconTask(attachmentInfo).executeParallel();
|
||||
}
|
||||
|
||||
private class UpdatePreviewIconTask extends EmailAsyncTask<Void, Void, Bitmap> {
|
||||
@ -1764,7 +1753,7 @@ public abstract class MessageViewFragmentBase extends Fragment implements View.O
|
||||
private final MessageViewAttachmentInfo mAttachmentInfo;
|
||||
|
||||
public UpdatePreviewIconTask(MessageViewAttachmentInfo attachmentInfo) {
|
||||
super(mUpdatePreviewIconTaskTracker);
|
||||
super(mTaskTracker);
|
||||
mContext = getActivity();
|
||||
mAttachmentInfo = attachmentInfo;
|
||||
}
|
||||
|
@ -57,8 +57,8 @@ public class MessageListXLRefreshTaskTest extends AndroidTestCase {
|
||||
final long ACCOUNT_ID = 5;
|
||||
final long MAILBOX_ID = 10;
|
||||
|
||||
MessageListXL.RefreshTask task = new MessageListXL.RefreshTask(getContext(), ACCOUNT_ID,
|
||||
MAILBOX_ID, mClock, mRefreshManager);
|
||||
MessageListXL.RefreshTask task = new MessageListXL.RefreshTask(null, getContext(),
|
||||
ACCOUNT_ID, MAILBOX_ID, mClock, mRefreshManager);
|
||||
|
||||
mRefreshManager.mExpectedAccountId = ACCOUNT_ID;
|
||||
|
||||
@ -100,8 +100,8 @@ public class MessageListXLRefreshTaskTest extends AndroidTestCase {
|
||||
final long ACCOUNT_ID = 5;
|
||||
final long MAILBOX_ID = 10;
|
||||
|
||||
MessageListXL.RefreshTask task = new MessageListXL.RefreshTask(getContext(), ACCOUNT_ID,
|
||||
MAILBOX_ID, mClock, mRefreshManager);
|
||||
MessageListXL.RefreshTask task = new MessageListXL.RefreshTask(null, getContext(),
|
||||
ACCOUNT_ID, MAILBOX_ID, mClock, mRefreshManager);
|
||||
|
||||
mRefreshManager.mExpectedAccountId = ACCOUNT_ID;
|
||||
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.emailcommon.utility;
|
||||
|
||||
import com.android.emailcommon.utility.EmailAsyncTask.Tracker;
|
||||
|
||||
import android.test.AndroidTestCase;
|
||||
import android.test.MoreAsserts;
|
||||
|
||||
@ -82,6 +84,37 @@ public class EmailAsyncTaskTests extends AndroidTestCase {
|
||||
task1.unregisterSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for {@link EmailAsyncTask.Tracker#cancelOthers}
|
||||
*/
|
||||
public void testCancellOthers() {
|
||||
final EmailAsyncTask.Tracker tracker = new EmailAsyncTask.Tracker();
|
||||
|
||||
final MyTask task1 = new MyTask(tracker);
|
||||
final MyTask task2 = new MyTask(tracker);
|
||||
final MyTask task3 = new MyTask(tracker);
|
||||
|
||||
final MyTask sub1 = new MyTaskSubClass(tracker);
|
||||
final MyTask sub2 = new MyTaskSubClass(tracker);
|
||||
final MyTask sub3 = new MyTaskSubClass(tracker);
|
||||
|
||||
// All should be in the tracker.
|
||||
assertEquals(6, tracker.getTaskCountForTest());
|
||||
|
||||
// This should remove task1, task2, but not task3 itself.
|
||||
tracker.cancelOthers(task3);
|
||||
|
||||
assertEquals(4, tracker.getTaskCountForTest());
|
||||
assertTrue(tracker.containsTaskForTest(task3));
|
||||
|
||||
// Same for sub1.
|
||||
tracker.cancelOthers(sub1);
|
||||
|
||||
assertEquals(2, tracker.getTaskCountForTest());
|
||||
assertTrue(tracker.containsTaskForTest(task3));
|
||||
assertTrue(tracker.containsTaskForTest(sub1));
|
||||
}
|
||||
|
||||
private static class MyTask extends EmailAsyncTask<String, String, String> {
|
||||
public String[] mDoInBackgroundArg;
|
||||
public String mDoInBackgroundResult;
|
||||
@ -108,4 +141,10 @@ public class EmailAsyncTaskTests extends AndroidTestCase {
|
||||
mOnPostExecuteArg = result;
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyTaskSubClass extends MyTask {
|
||||
public MyTaskSubClass(Tracker tracker) {
|
||||
super(tracker);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user