Remove Handlers from Activities.

AccountFolderList, MessageCompose and MailboxList.

Also,
- ControllerResultUiThreadWrapper now takes a Handler instead of an Activity.
  So that it can be used from a Service as well.

- ControllerResultUiThreadWrapper.getWrappee() to get the wrapped object.
  We'll eventually need this.

- I'll work on MessageList too, but the might be relatively
  large, so I'll do that in a separate CL

Change-Id: I281d88d5af1834248ec3f7463f0df3f5635149be
This commit is contained in:
Makoto Onuki 2010-06-01 14:09:11 -07:00
parent 0a892ae04f
commit 4a2615e2a5
5 changed files with 63 additions and 161 deletions

View File

@ -19,24 +19,28 @@ package com.android.email;
import com.android.email.Controller.Result;
import com.android.email.mail.MessagingException;
import android.app.Activity;
import android.os.Handler;
/**
* A {@link Result} that wraps another {@link Result} and makes sure methods gets called back
* on the UI thread.
*/
public class ControllerResultUiThreadWrapper implements Result {
private final Activity mActivity;
private final Result mWrappee;
public class ControllerResultUiThreadWrapper<T extends Result> implements Result {
private final Handler mHandler;
private final T mWrappee;
public ControllerResultUiThreadWrapper(Activity activity, Result wrappee) {
mActivity = activity;
public ControllerResultUiThreadWrapper(Handler handler, T wrappee) {
mHandler = handler;
mWrappee = wrappee;
}
public T getWrappee() {
return mWrappee;
}
public void loadAttachmentCallback(final MessagingException result, final long messageId,
final long attachmentId, final int progress) {
mActivity.runOnUiThread(new Runnable() {
mHandler.post(new Runnable() {
public void run() {
mWrappee.loadAttachmentCallback(result, messageId, attachmentId, progress);
}
@ -45,7 +49,7 @@ public class ControllerResultUiThreadWrapper implements Result {
public void loadMessageForViewCallback(final MessagingException result,
final long messageId, final int progress) {
mActivity.runOnUiThread(new Runnable() {
mHandler.post(new Runnable() {
public void run() {
mWrappee.loadMessageForViewCallback(result, messageId, progress);
}
@ -54,7 +58,7 @@ public class ControllerResultUiThreadWrapper implements Result {
public void sendMailCallback(final MessagingException result, final long accountId,
final long messageId, final int progress) {
mActivity.runOnUiThread(new Runnable() {
mHandler.post(new Runnable() {
public void run() {
mWrappee.sendMailCallback(result, accountId, messageId, progress);
}
@ -63,7 +67,7 @@ public class ControllerResultUiThreadWrapper implements Result {
public void serviceCheckMailCallback(final MessagingException result, final long accountId,
final long mailboxId, final int progress, final long tag) {
mActivity.runOnUiThread(new Runnable() {
mHandler.post(new Runnable() {
public void run() {
mWrappee.serviceCheckMailCallback(result, accountId, mailboxId, progress, tag);
}
@ -72,7 +76,7 @@ public class ControllerResultUiThreadWrapper implements Result {
public void updateMailboxCallback(final MessagingException result, final long accountId,
final long mailboxId, final int progress, final int numNewMessages) {
mActivity.runOnUiThread(new Runnable() {
mHandler.post(new Runnable() {
public void run() {
mWrappee.updateMailboxCallback(result, accountId, mailboxId, progress,
numNewMessages);
@ -82,7 +86,7 @@ public class ControllerResultUiThreadWrapper implements Result {
public void updateMailboxListCallback(final MessagingException result, final long accountId,
final int progress) {
mActivity.runOnUiThread(new Runnable() {
mHandler.post(new Runnable() {
public void run() {
mWrappee.updateMailboxListCallback(result, accountId, progress);
}

View File

@ -18,6 +18,7 @@ package com.android.email.activity;
import com.android.email.AccountBackupRestore;
import com.android.email.Controller;
import com.android.email.ControllerResultUiThreadWrapper;
import com.android.email.Email;
import com.android.email.R;
import com.android.email.SecurityPolicy;
@ -87,8 +88,7 @@ public class AccountFolderList extends ListActivity
private LoadAccountsTask mLoadAccountsTask;
private DeleteAccountTask mDeleteAccountTask;
private MessageListHandler mHandler;
private ControllerResults mControllerCallback;
private Controller.Result mControllerCallback;
private static final String FAVORITE_COUNT_SELECTION =
MessageColumns.FLAG_FAVORITE + "= 1";
@ -122,8 +122,8 @@ public class AccountFolderList extends ListActivity
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,
R.layout.list_title);
mHandler = new MessageListHandler();
mControllerCallback = new ControllerResults();
mControllerCallback = new ControllerResultUiThreadWrapper<ControllerResults>(
new Handler(), new ControllerResults());
mProgressIcon = (ProgressBar) findViewById(R.id.title_progress_icon);
mListView = getListView();
@ -188,7 +188,7 @@ public class AccountFolderList extends ListActivity
Utility.cancelTask(mDeleteAccountTask, false); // Don't interrupt if it's running.
mDeleteAccountTask = null;
if (mListAdapter != null) {
if (mListAdapter != null) {
mListAdapter.changeCursor(null);
}
}
@ -197,7 +197,7 @@ public class AccountFolderList extends ListActivity
if (mListAdapter.isMailbox(position)) {
MessageList.actionHandleMailbox(this, id);
} else if (mListAdapter.isAccount(position)) {
MessageList.actionHandleAccount(this, id, Mailbox.TYPE_INBOX);
MessageList.actionHandleAccount(this, id, Mailbox.TYPE_INBOX);
}
}
@ -247,7 +247,7 @@ public class AccountFolderList extends ListActivity
/**
* Build the group and child cursors that support the summary views (aka "at a glance").
*
*
* This is a placeholder implementation with significant problems that need to be addressed:
*
* TODO: We should only show summary mailboxes if they are non-empty. So there needs to be
@ -407,7 +407,7 @@ public class AccountFolderList extends ListActivity
Toast.makeText(this, getString(R.string.account_folder_list_refresh_toast),
Toast.LENGTH_LONG).show();
} else {
mHandler.progress(true);
showProgressIcon(true);
Controller.getInstance(getApplication()).updateMailboxList(
accountId, mControllerCallback);
}
@ -586,43 +586,14 @@ public class AccountFolderList extends ListActivity
}
return super.onKeyDown(keyCode, event);
}
/**
* Handler for UI-thread operations (when called from callbacks or any other threads)
*/
private class MessageListHandler extends Handler {
private static final int MSG_PROGRESS = 1;
@Override
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case MSG_PROGRESS:
boolean showProgress = (msg.arg1 != 0);
if (showProgress) {
mProgressIcon.setVisibility(View.VISIBLE);
} else {
mProgressIcon.setVisibility(View.GONE);
}
break;
default:
super.handleMessage(msg);
}
}
/**
* Call from any thread to start/stop progress indicator(s)
* @param progress true to start, false to stop
*/
public void progress(boolean progress) {
android.os.Message msg = android.os.Message.obtain();
msg.what = MSG_PROGRESS;
msg.arg1 = progress ? 1 : 0;
sendMessage(msg);
}
private void showProgressIcon(boolean show) {
mProgressIcon.setVisibility(show ? View.VISIBLE : View.GONE);
}
/**
* Callback for async Controller results.
* Controller results listener. We wrap it with {@link ControllerResultUiThreadWrapper},
* so all methods are called on the UI thread.
*/
private class ControllerResults implements Controller.Result {
public void updateMailboxListCallback(MessagingException result, long accountKey,
@ -662,11 +633,7 @@ public class AccountFolderList extends ListActivity
}
private void updateProgress(MessagingException result, int progress) {
if (result != null || progress == 100) {
mHandler.progress(false);
} else if (progress == 0) {
mHandler.progress(true);
}
showProgressIcon(result == null && progress < 100);
}
}
}

View File

@ -17,6 +17,7 @@
package com.android.email.activity;
import com.android.email.Controller;
import com.android.email.ControllerResultUiThreadWrapper;
import com.android.email.Email;
import com.android.email.R;
import com.android.email.Utility;
@ -72,8 +73,7 @@ public class MailboxList extends ListActivity implements OnItemClickListener, On
private TextView mErrorBanner;
private MailboxListAdapter mListAdapter;
private MailboxListHandler mHandler;
private ControllerResults mControllerCallback;
private Controller.Result mControllerCallback;
// DB access
private long mAccountId;
@ -86,7 +86,7 @@ public class MailboxList extends ListActivity implements OnItemClickListener, On
/**
* Open a specific account.
*
*
* @param context
* @param accountId the account to view
*/
@ -102,8 +102,8 @@ public class MailboxList extends ListActivity implements OnItemClickListener, On
super.onCreate(icicle);
setContentView(R.layout.mailbox_list);
mHandler = new MailboxListHandler();
mControllerCallback = new ControllerResults();
mControllerCallback = new ControllerResultUiThreadWrapper<ControllerResults>(
new Handler(), new ControllerResults());
mListView = getListView();
mProgressIcon = (ProgressBar) findViewById(R.id.title_progress_icon);
mErrorBanner = (TextView) findViewById(R.id.connection_error_text);
@ -146,7 +146,7 @@ public class MailboxList extends ListActivity implements OnItemClickListener, On
int nAccounts = EmailContent.count(MailboxList.this, Account.CONTENT_URI, null, null);
return new Object[] {accountName, nAccounts};
}
@Override
protected void onPostExecute(Object[] result) {
if (result == null) {
@ -279,7 +279,7 @@ public class MailboxList extends ListActivity implements OnItemClickListener, On
*/
private void onRefresh(long mailboxId) {
Controller controller = Controller.getInstance(getApplication());
mHandler.progress(true);
showProgressIcon(true);
if (mailboxId >= 0) {
controller.updateMailbox(mAccountId, mailboxId, mControllerCallback);
} else {
@ -411,74 +411,33 @@ public class MailboxList extends ListActivity implements OnItemClickListener, On
mMessageCountTask = (MessageCountTask) new MessageCountTask().execute();
}
/**
* Handler for UI-thread operations (when called from callbacks or any other threads)
*/
class MailboxListHandler extends Handler {
private static final int MSG_PROGRESS = 1;
private static final int MSG_ERROR_BANNER = 2;
private void showProgressIcon(boolean show) {
mProgressIcon.setVisibility(show ? View.VISIBLE : View.GONE);
}
@Override
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case MSG_PROGRESS:
boolean showProgress = (msg.arg1 != 0);
if (showProgress) {
mProgressIcon.setVisibility(View.VISIBLE);
} else {
mProgressIcon.setVisibility(View.GONE);
}
break;
case MSG_ERROR_BANNER:
String message = (String) msg.obj;
boolean isVisible = mErrorBanner.getVisibility() == View.VISIBLE;
if (message != null) {
mErrorBanner.setText(message);
if (!isVisible) {
mErrorBanner.setVisibility(View.VISIBLE);
mErrorBanner.startAnimation(
AnimationUtils.loadAnimation(
MailboxList.this, R.anim.header_appear));
}
} else {
if (isVisible) {
mErrorBanner.setVisibility(View.GONE);
mErrorBanner.startAnimation(
AnimationUtils.loadAnimation(
MailboxList.this, R.anim.header_disappear));
}
}
break;
default:
super.handleMessage(msg);
private void showErrorBanner(String message) {
boolean isVisible = mErrorBanner.getVisibility() == View.VISIBLE;
if (message != null) {
mErrorBanner.setText(message);
if (!isVisible) {
mErrorBanner.setVisibility(View.VISIBLE);
mErrorBanner.startAnimation(
AnimationUtils.loadAnimation(
MailboxList.this, R.anim.header_appear));
}
} else {
if (isVisible) {
mErrorBanner.setVisibility(View.GONE);
mErrorBanner.startAnimation(
AnimationUtils.loadAnimation(
MailboxList.this, R.anim.header_disappear));
}
}
/**
* Call from any thread to start/stop progress indicator(s)
* @param progress true to start, false to stop
*/
public void progress(boolean progress) {
android.os.Message msg = android.os.Message.obtain();
msg.what = MSG_PROGRESS;
msg.arg1 = progress ? 1 : 0;
sendMessage(msg);
}
/**
* Called from any thread to show or hide the connection error banner.
* @param message error text or null to hide the box
*/
public void showErrorBanner(String message) {
android.os.Message msg = android.os.Message.obtain();
msg.what = MSG_ERROR_BANNER;
msg.obj = message;
sendMessage(msg);
}
}
/**
* Callback for async Controller results.
* Controller results listener. We wrap it with {@link ControllerResultUiThreadWrapper},
* so all methods are called on the UI thread.
*/
private class ControllerResults implements Controller.Result {
@ -524,11 +483,7 @@ public class MailboxList extends ListActivity implements OnItemClickListener, On
}
private void updateProgress(MessagingException result, int progress) {
if (result != null || progress == 100) {
mHandler.progress(false);
} else if (progress == 0) {
mHandler.progress(true);
}
showProgressIcon(result == null && progress < 100);
}
/**
@ -563,9 +518,9 @@ public class MailboxList extends ListActivity implements OnItemClickListener, On
break;
}
}
mHandler.showErrorBanner(getString(id));
showErrorBanner(getString(id));
} else if (progress > 0) {
mHandler.showErrorBanner(null);
showErrorBanner(null);
}
}
}

View File

@ -47,7 +47,6 @@ import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Parcelable;
import android.provider.OpenableColumns;
import android.text.InputFilter;
@ -97,10 +96,6 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
private static final String STATE_KEY_DRAFT_ID =
"com.android.email.activity.MessageCompose.draftId";
private static final int MSG_UPDATE_TITLE = 3;
private static final int MSG_SKIPPED_ATTACHMENTS = 4;
private static final int MSG_DISCARDED_DRAFT = 6;
private static final int ACTIVITY_REQUEST_PICK_ATTACHMENT = 1;
private static final String[] ATTACHMENT_META_COLUMNS = {
@ -161,26 +156,6 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
private EmailAddressAdapter mAddressAdapterCc;
private EmailAddressAdapter mAddressAdapterBcc;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case MSG_UPDATE_TITLE:
updateTitle();
break;
case MSG_SKIPPED_ATTACHMENTS:
Toast.makeText(
MessageCompose.this,
getString(R.string.message_compose_attachments_skipped_toast),
Toast.LENGTH_LONG).show();
break;
default:
super.handleMessage(msg);
break;
}
}
};
/**
* Compose a new message using the given account. If account is -1 the default account
* will be used.
@ -1476,7 +1451,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
displayQuotedText(message.mText, message.mHtml);
// TODO: re-enable loadAttachments below
// if (!loadAttachments(message, 0)) {
// mHandler.sendEmptyMessage(MSG_SKIPPED_ATTACHMENTS);
// Utility.showToast(this, R.string.message_compose_attachments_skipped_toast);
// }
} else if (ACTION_EDIT_DRAFT.equals(mAction)) {
mSubjectView.setText(subject);

View File

@ -217,7 +217,8 @@ public class MessageView extends Activity implements OnClickListener {
super.onCreate(icicle);
setContentView(R.layout.message_view);
mControllerCallback = new ControllerResultUiThreadWrapper(this, new ControllerResults());
mControllerCallback = new ControllerResultUiThreadWrapper<ControllerResults>(
new Handler(), new ControllerResults());
mSubjectView = (TextView) findViewById(R.id.subject);
mFromView = (TextView) findViewById(R.id.from);