From 2c74ee56a44e7a43bda14e88fd2b571fd88952fe Mon Sep 17 00:00:00 2001 From: Marc Blank Date: Sun, 11 Oct 2009 18:55:45 -0700 Subject: [PATCH] Prevent EmailAddressAdapter from leaking cursors; load in bg * Relates to a number of bugs related to ANR's and slow behavior when addressing mail * Call changeCursor(null) on the Adapter when the activity is destroyed * Call getCount() in the background thread to force data there rather than in the UI thread * If this change is accepted, something equivalent should be used in the Gmail app as well * Addresses #2180237 (P1, target Eclair_Sholes) as well as #2180976 and #2146926, the latter two of which were fixed with workarounds. Change-Id: I7503c5fbe091dbc5e784d5a7bebeb3d60226d57d --- src/com/android/email/EmailAddressAdapter.java | 11 ++++++++++- .../android/email/activity/MessageCompose.java | 15 +++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/com/android/email/EmailAddressAdapter.java b/src/com/android/email/EmailAddressAdapter.java index fbe78094f..e4d68707c 100644 --- a/src/com/android/email/EmailAddressAdapter.java +++ b/src/com/android/email/EmailAddressAdapter.java @@ -69,6 +69,15 @@ public class EmailAddressAdapter extends ResourceCursorAdapter { public Cursor runQueryOnBackgroundThread(CharSequence constraint) { String filter = constraint == null ? "" : constraint.toString(); Uri uri = Uri.withAppendedPath(Email.CONTENT_FILTER_URI, Uri.encode(filter)); - return mContentResolver.query(uri, PROJECTION, null, null, SORT_ORDER); + Cursor c = mContentResolver.query(uri, PROJECTION, null, null, SORT_ORDER); + // To prevent expensive execution in the UI thread + // Cursors get lazily executed, so if you don't call anything on the cursor before + // returning it from the background thread you'll have a complied program for the cursor, + // but it won't have been executed to generate the data yet. Often the execution is more + // expensive than the compilation... + if (c != null) { + c.getCount(); + } + return c; } } diff --git a/src/com/android/email/activity/MessageCompose.java b/src/com/android/email/activity/MessageCompose.java index 1084becc0..e8837e746 100644 --- a/src/com/android/email/activity/MessageCompose.java +++ b/src/com/android/email/activity/MessageCompose.java @@ -148,6 +148,8 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus private AsyncTask mSaveMessageTask; private AsyncTask mLoadMessageTask; + private EmailAddressAdapter mAddressAdapter; + private Handler mHandler = new Handler() { @Override public void handleMessage(android.os.Message msg) { @@ -375,6 +377,11 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus cancelTask(mLoadMessageTask); mLoadMessageTask = null; // don't cancel mSaveMessageTask, let it do its job to the end. + + // Make sure the adapter doesn't leak its cursor + if (mAddressAdapter != null) { + mAddressAdapter.changeCursor(null); + } } /** @@ -511,18 +518,18 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus mQuotedTextDelete.setOnClickListener(this); - EmailAddressAdapter addressAdapter = new EmailAddressAdapter(this); + mAddressAdapter = new EmailAddressAdapter(this); EmailAddressValidator addressValidator = new EmailAddressValidator(); - mToView.setAdapter(addressAdapter); + mToView.setAdapter(mAddressAdapter); mToView.setTokenizer(new Rfc822Tokenizer()); mToView.setValidator(addressValidator); - mCcView.setAdapter(addressAdapter); + mCcView.setAdapter(mAddressAdapter); mCcView.setTokenizer(new Rfc822Tokenizer()); mCcView.setValidator(addressValidator); - mBccView.setAdapter(addressAdapter); + mBccView.setAdapter(mAddressAdapter); mBccView.setTokenizer(new Rfc822Tokenizer()); mBccView.setValidator(addressValidator);