Clear references to inner classes in onDestroy().

Also
- Made inner classes private if possible.
- Made some members final.

Bug 2570603

Change-Id: I34451000f2540c67e1039ea9dc4839dbec5ffab7
This commit is contained in:
Makoto Onuki 2010-04-06 10:25:15 -07:00
parent c94c077a66
commit 59cf1d05c1
8 changed files with 110 additions and 101 deletions

View File

@ -31,6 +31,7 @@ import android.content.Context;
import android.content.res.TypedArray;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.text.Editable;
import android.util.Base64;
import android.widget.TextView;
@ -506,4 +507,24 @@ public class Utility {
public static String replaceBareLfWithCrlf(String str) {
return str.replace("\r", "").replace("\n", "\r\n");
}
/**
* Cancel an {@link AsyncTask}. If it's already running, it'll be interrupted.
*/
public static void cancelTaskInterrupt(AsyncTask<?, ?, ?> task) {
cancelTask(task, true);
}
/**
* Cancel an {@link AsyncTask}.
*
* @param mayInterruptIfRunning <tt>true</tt> if the thread executing this
* task should be interrupted; otherwise, in-progress tasks are allowed
* to complete.
*/
public static void cancelTask(AsyncTask<?, ?, ?> task, boolean mayInterruptIfRunning) {
if (task != null && task.getStatus() != AsyncTask.Status.FINISHED) {
task.cancel(mayInterruptIfRunning);
}
}
}

View File

@ -91,9 +91,8 @@ public class AccountFolderList extends ListActivity implements OnItemClickListen
private LoadAccountsTask mLoadAccountsTask;
private DeleteAccountTask mDeleteAccountTask;
private MessageListHandler mHandler = new MessageListHandler();
private ControllerResults mControllerCallback = new ControllerResults();
private MessageListHandler mHandler;
private ControllerResults mControllerCallback;
/**
* Reduced mailbox projection used by AccountsAdapter
@ -154,6 +153,8 @@ public class AccountFolderList extends ListActivity implements OnItemClickListen
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,
R.layout.list_title);
mHandler = new MessageListHandler();
mControllerCallback = new ControllerResults();
mProgressIcon = (ProgressBar) findViewById(R.id.title_progress_icon);
mListView = getListView();
@ -203,19 +204,21 @@ public class AccountFolderList extends ListActivity implements OnItemClickListen
@Override
protected void onDestroy() {
super.onDestroy();
Utility.cancelTaskInterrupt(mLoadAccountsTask);
mLoadAccountsTask = null;
if (mLoadAccountsTask != null &&
mLoadAccountsTask.getStatus() != LoadAccountsTask.Status.FINISHED) {
mLoadAccountsTask.cancel(true);
mLoadAccountsTask = null;
}
if (mDeleteAccountTask != null &&
mDeleteAccountTask.getStatus() != DeleteAccountTask.Status.FINISHED) {
mDeleteAccountTask.cancel(false); // false == allow the cancel to run to completion
mDeleteAccountTask = null;
}
// TODO: We shouldn't call cancel() for DeleteAccountTask. If the task hasn't
// started, this will mark it as "don't run", but we always want it to finish.
// (But don't just remove this cancel() call. DeleteAccountTask.onPostExecute() checks if
// it's been canceled to decided whether to update the UI.)
Utility.cancelTask(mDeleteAccountTask, false); // Don't interrupt if it's running.
mDeleteAccountTask = null;
mListAdapter.changeCursor(null);
mListAdapter = null;
mHandler = null;
mControllerCallback = null;
}
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
@ -357,8 +360,8 @@ public class AccountFolderList extends ListActivity implements OnItemClickListen
}
private class DeleteAccountTask extends AsyncTask<Void, Void, Void> {
private long mAccountId;
private String mAccountUri;
private final long mAccountId;
private final String mAccountUri;
public DeleteAccountTask(long accountId, String accountUri) {
mAccountId = accountId;
@ -395,10 +398,7 @@ public class AccountFolderList extends ListActivity implements OnItemClickListen
}
private void updateAccounts() {
if (mLoadAccountsTask != null &&
mLoadAccountsTask.getStatus() != LoadAccountsTask.Status.FINISHED) {
mLoadAccountsTask.cancel(true);
}
Utility.cancelTaskInterrupt(mLoadAccountsTask);
mLoadAccountsTask = (LoadAccountsTask) new LoadAccountsTask().execute();
}
@ -468,6 +468,7 @@ public class AccountFolderList extends ListActivity implements OnItemClickListen
int numAccounts = EmailContent.count(AccountFolderList.this,
Account.CONTENT_URI, null, null);
mListAdapter.addOnDeletingAccount(mSelectedContextAccount.mId);
mDeleteAccountTask = (DeleteAccountTask) new DeleteAccountTask(
mSelectedContextAccount.mId,
mSelectedContextAccount.getStoreUri(AccountFolderList.this)).execute();
@ -603,7 +604,7 @@ public class AccountFolderList extends ListActivity implements OnItemClickListen
/**
* Handler for UI-thread operations (when called from callbacks or any other threads)
*/
class MessageListHandler extends Handler {
private class MessageListHandler extends Handler {
private static final int MSG_PROGRESS = 1;
@Override
@ -685,12 +686,12 @@ public class AccountFolderList extends ListActivity implements OnItemClickListen
/* package */ static class AccountsAdapter extends CursorAdapter {
Context mContext;
private LayoutInflater mInflater;
private int mMailboxesCount;
private int mSeparatorPosition;
long mDefaultAccountId;
ArrayList<Long> mOnDeletingAccounts = new ArrayList<Long>();
private final Context mContext;
private final LayoutInflater mInflater;
private final int mMailboxesCount;
private final int mSeparatorPosition;
private final long mDefaultAccountId;
private final ArrayList<Long> mOnDeletingAccounts = new ArrayList<Long>();
public static AccountsAdapter getInstance(Cursor mailboxesCursor, Cursor accountsCursor,
Context context, long defaultAccountId) {

View File

@ -77,8 +77,8 @@ public class MailboxList extends ListActivity implements OnItemClickListener, On
private TextView mErrorBanner;
private MailboxListAdapter mListAdapter;
private MailboxListHandler mHandler = new MailboxListHandler();
private ControllerResults mControllerCallback = new ControllerResults();
private MailboxListHandler mHandler;
private ControllerResults mControllerCallback;
// DB access
private long mAccountId;
@ -109,6 +109,8 @@ public class MailboxList extends ListActivity implements OnItemClickListener, On
super.onCreate(icicle);
setContentView(R.layout.mailbox_list);
mHandler = new MailboxListHandler();
mControllerCallback = new ControllerResults();
mListView = getListView();
mProgressIcon = (ProgressBar) findViewById(R.id.title_progress_icon);
mErrorBanner = (TextView) findViewById(R.id.connection_error_text);
@ -189,22 +191,17 @@ public class MailboxList extends ListActivity implements OnItemClickListener, On
protected void onDestroy() {
super.onDestroy();
if (mLoadMailboxesTask != null &&
mLoadMailboxesTask.getStatus() != LoadMailboxesTask.Status.FINISHED) {
mLoadMailboxesTask.cancel(true);
mLoadMailboxesTask = null;
}
if (mLoadAccountNameTask != null &&
mLoadAccountNameTask.getStatus() != LoadMailboxesTask.Status.FINISHED) {
mLoadAccountNameTask.cancel(true);
mLoadAccountNameTask = null;
}
if (mMessageCountTask != null &&
mMessageCountTask.getStatus() != MessageCountTask.Status.FINISHED) {
mMessageCountTask.cancel(true);
mMessageCountTask = null;
}
Utility.cancelTaskInterrupt(mLoadMailboxesTask);
mLoadMailboxesTask = null;
Utility.cancelTaskInterrupt(mLoadAccountNameTask);
mLoadAccountNameTask = null;
Utility.cancelTaskInterrupt(mMessageCountTask);
mMessageCountTask = null;
mListAdapter.changeCursor(null);
mListAdapter = null;
mHandler = null;
mControllerCallback = null;
}
public void onClick(View v) {

View File

@ -150,7 +150,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
private TextView mRightTitle;
private Controller mController;
private Listener mListener = new Listener();
private Listener mListener;
private boolean mDraftNeedsSaving;
private boolean mMessageLoaded;
private AsyncTask mLoadAttachmentsTask;
@ -295,6 +295,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.list_title);
mController = Controller.getInstance(getApplication());
mListener = new Listener();
initViews();
setDraftNeedsSaving(false);
@ -376,12 +377,6 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
mController.removeResultCallback(mListener);
}
private static void cancelTask(AsyncTask<?, ?, ?> task) {
if (task != null && task.getStatus() != AsyncTask.Status.FINISHED) {
task.cancel(true);
}
}
/**
* We override onDestroy to make sure that the WebView gets explicitly destroyed.
* Otherwise it can leak native references.
@ -391,22 +386,28 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
super.onDestroy();
mQuotedText.destroy();
mQuotedText = null;
cancelTask(mLoadAttachmentsTask);
Utility.cancelTaskInterrupt(mLoadAttachmentsTask);
mLoadAttachmentsTask = null;
cancelTask(mLoadMessageTask);
Utility.cancelTaskInterrupt(mLoadMessageTask);
mLoadMessageTask = null;
// don't cancel mSaveMessageTask, let it do its job to the end.
mSaveMessageTask = null;
// TODO Make sure the three adapters don't leak their internal cursors
if (mAddressAdapterTo != null) {
mAddressAdapterTo.changeCursor(null);
mAddressAdapterTo = null;
}
if (mAddressAdapterCc != null) {
mAddressAdapterCc.changeCursor(null);
mAddressAdapterCc = null;
}
if (mAddressAdapterBcc != null) {
mAddressAdapterBcc.changeCursor(null);
mAddressAdapterBcc = null;
}
mHandler = null;
mListener = null;
}
/**
@ -1544,7 +1545,7 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus
}
}
class Listener implements Controller.Result {
private class Listener implements Controller.Result {
public void updateMailboxListCallback(MessagingException result, long accountId,
int progress) {
}

View File

@ -110,9 +110,10 @@ public class MessageList extends ListActivity implements OnItemClickListener, On
private int mListFooterMode;
private MessageListAdapter mListAdapter;
private MessageListHandler mHandler = new MessageListHandler();
private Controller mController = Controller.getInstance(getApplication());
private ControllerResults mControllerCallback = new ControllerResults();
private MessageListHandler mHandler;
private final Controller mController = Controller.getInstance(getApplication());
private ControllerResults mControllerCallback;
private TextView mLeftTitle;
private ProgressBar mProgressIcon;
@ -228,6 +229,8 @@ public class MessageList extends ListActivity implements OnItemClickListener, On
super.onCreate(icicle);
setContentView(R.layout.message_list);
mHandler = new MessageListHandler();
mControllerCallback = new ControllerResults();
mCanAutoRefresh = true;
mListView = getListView();
mMultiSelectPanel = findViewById(R.id.footer_organize);
@ -315,28 +318,19 @@ public class MessageList extends ListActivity implements OnItemClickListener, On
protected void onDestroy() {
super.onDestroy();
if (mLoadMessagesTask != null &&
mLoadMessagesTask.getStatus() != LoadMessagesTask.Status.FINISHED) {
mLoadMessagesTask.cancel(true);
mLoadMessagesTask = null;
}
if (mFindMailboxTask != null &&
mFindMailboxTask.getStatus() != FindMailboxTask.Status.FINISHED) {
mFindMailboxTask.cancel(true);
mFindMailboxTask = null;
}
if (mSetTitleTask != null &&
mSetTitleTask.getStatus() != SetTitleTask.Status.FINISHED) {
mSetTitleTask.cancel(true);
mSetTitleTask = null;
}
if (mSetFooterTask != null &&
mSetFooterTask.getStatus() != SetTitleTask.Status.FINISHED) {
mSetFooterTask.cancel(true);
mSetFooterTask = null;
}
Utility.cancelTaskInterrupt(mLoadMessagesTask);
mLoadMessagesTask = null;
Utility.cancelTaskInterrupt(mFindMailboxTask);
mFindMailboxTask = null;
Utility.cancelTaskInterrupt(mSetTitleTask);
mSetTitleTask = null;
Utility.cancelTaskInterrupt(mSetFooterTask);
mSetFooterTask = null;
mListAdapter.changeCursor(null);
mListAdapter = null;
mHandler = null;
mControllerCallback = null;
}
@Override

View File

@ -156,9 +156,9 @@ public class MessageView extends Activity implements OnClickListener {
private Drawable mFavoriteIconOn;
private Drawable mFavoriteIconOff;
private MessageViewHandler mHandler = new MessageViewHandler();
private MessageViewHandler mHandler;
private Controller mController;
private ControllerResults mControllerCallback = new ControllerResults();
private ControllerResults mControllerCallback;
private View mMoveToNewer;
private View mMoveToOlder;
@ -176,7 +176,7 @@ public class MessageView extends Activity implements OnClickListener {
// this is true when reply & forward are disabled, such as messages in the trash
private boolean mDisableReplyAndForward;
class MessageViewHandler extends Handler {
private class MessageViewHandler extends Handler {
private static final int MSG_PROGRESS = 1;
private static final int MSG_ATTACHMENT_PROGRESS = 2;
private static final int MSG_LOAD_CONTENT_URI = 3;
@ -346,6 +346,9 @@ public class MessageView extends Activity implements OnClickListener {
super.onCreate(icicle);
setContentView(R.layout.message_view);
mHandler = new MessageViewHandler();
mControllerCallback = new ControllerResults();
mSubjectView = (TextView) findViewById(R.id.subject);
mFromView = (TextView) findViewById(R.id.from);
mToView = (TextView) findViewById(R.id.to);
@ -472,22 +475,16 @@ public class MessageView extends Activity implements OnClickListener {
}
}
private static void cancelTask(AsyncTask<?, ?, ?> task) {
if (task != null && task.getStatus() != AsyncTask.Status.FINISHED) {
task.cancel(true);
}
}
private void cancelAllTasks() {
cancelTask(mLoadMessageTask);
Utility.cancelTaskInterrupt(mLoadMessageTask);
mLoadMessageTask = null;
cancelTask(mLoadBodyTask);
Utility.cancelTaskInterrupt(mLoadBodyTask);
mLoadBodyTask = null;
cancelTask(mLoadAttachmentsTask);
Utility.cancelTaskInterrupt(mLoadAttachmentsTask);
mLoadAttachmentsTask = null;
cancelTask(mLoadMessageListTask);
Utility.cancelTaskInterrupt(mLoadMessageListTask);
mLoadMessageListTask = null;
cancelTask(mPresenceCheckTask);
Utility.cancelTaskInterrupt(mPresenceCheckTask);
mPresenceCheckTask = null;
}
@ -505,6 +502,9 @@ public class MessageView extends Activity implements OnClickListener {
mMessageContentView = null;
}
// the cursor was closed in onPause()
mHandler = null;
mControllerCallback = null;
}
private void onDelete() {
@ -1433,7 +1433,7 @@ public class MessageView extends Activity implements OnClickListener {
/**
* Controller results listener. This completely replaces MessagingListener
*/
class ControllerResults implements Controller.Result {
private class ControllerResults implements Controller.Result {
public void loadMessageForViewCallback(MessagingException result, long messageId,
int progress) {
@ -1662,7 +1662,7 @@ public class MessageView extends Activity implements OnClickListener {
private Context mContext;
private MediaScannerConnection mConnection;
private File mFile;
MessageViewHandler mHandler;
private MessageViewHandler mHandler;
public MediaScannerNotifier(Context context, File file, MessageViewHandler handler) {
mContext = context;

View File

@ -21,6 +21,7 @@ import com.android.email.Email;
import com.android.email.LegacyConversions;
import com.android.email.Preferences;
import com.android.email.R;
import com.android.email.Utility;
import com.android.email.activity.setup.AccountSettingsUtils;
import com.android.email.activity.setup.AccountSettingsUtils.Provider;
import com.android.email.mail.FetchProfile;
@ -134,11 +135,8 @@ public class UpgradeAccounts extends ListActivity implements OnClickListener {
protected void onDestroy() {
super.onDestroy();
if (mConversionTask != null &&
mConversionTask.getStatus() != ConversionTask.Status.FINISHED) {
mConversionTask.cancel(false);
mConversionTask = null;
}
Utility.cancelTask(mConversionTask, false); // false = Don't interrupt running task
mConversionTask = null;
}
/**

View File

@ -16,16 +16,13 @@
package com.android.email.activity;
import com.android.email.Account;
import com.android.email.AccountBackupRestore;
import com.android.email.ExchangeUtils;
import com.android.email.Preferences;
import com.android.email.activity.setup.AccountSetupBasics;
import com.android.email.provider.EmailContent;
import com.android.email.provider.EmailContent.Mailbox;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;