From 23bc9b72b81fb76136720554a0633f1400a200ca Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Tue, 23 Mar 2010 23:27:34 -0700 Subject: [PATCH] Hopefully fix frequently-reported ViewContactActivity ANR. See background in bug 2539603. BUG=2539603 Change-Id: I1392e8767a6174048c59a782076663772a3402d1 --- src/com/android/contacts/ViewContactActivity.java | 72 +++++++++++++++-------- 1 file changed, 46 insertions(+), 26 deletions(-) diff --git a/src/com/android/contacts/ViewContactActivity.java b/src/com/android/contacts/ViewContactActivity.java index b94ad98..1f16715 100644 --- a/src/com/android/contacts/ViewContactActivity.java +++ b/src/com/android/contacts/ViewContactActivity.java @@ -49,6 +49,7 @@ import android.graphics.drawable.Drawable; import android.net.ParseException; import android.net.Uri; import android.net.WebAddress; +import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.RemoteException; @@ -305,7 +306,7 @@ public class ViewContactActivity extends Activity } /** {@inheritDoc} */ - public void onQueryComplete(int token, Object cookie, Cursor cursor) { + public void onQueryComplete(int token, Object cookie, final Cursor cursor) { if (token == TOKEN_STATUSES) { try { // Read available social rows and consider binding @@ -315,16 +316,51 @@ public class ViewContactActivity extends Activity cursor.close(); } } - } else { - EntityIterator iterator = RawContacts.newEntityIterator(cursor); - try { - // Read incoming entities and consider binding - readEntities(iterator); - } finally { - iterator.close(); - } + considerBindData(); + return; } - considerBindData(); + + // We also have to iterate over the Cursor in the background, + // as iterating over the Cursor can ANR on large result sets, + // especially as our ContentProvider is cross-process. + final ArrayList oldEntities = mEntities; + (new AsyncTask>() { + @Override + protected ArrayList doInBackground(Void... params) { + ArrayList newEntities = Lists.newArrayList(); + EntityIterator iterator = RawContacts.newEntityIterator(cursor); + try { + while (iterator.hasNext()) { + Entity entity = iterator.next(); + newEntities.add(entity); + } + } catch (RemoteException e) { + Log.w(TAG, "Problem reading contact data: " + e.toString()); + return null; + } finally { + iterator.close(); + } + return newEntities; + } + + @Override + protected void onPostExecute(ArrayList newEntities) { + if (newEntities == null) { + // There was an error loading. + return; + } + synchronized (ViewContactActivity.this) { + if (mEntities != oldEntities) { + // Multiple async tasks were in flight and we + // lost the race. + return; + } + mEntities = newEntities; + mHasEntities = true; + } + considerBindData(); + } + }).execute(); } private long getRefreshedContactId() { @@ -336,22 +372,6 @@ public class ViewContactActivity extends Activity } /** - * Read from the given {@link EntityIterator} to build internal set of - * {@link #mEntities} for data display. - */ - private synchronized void readEntities(EntityIterator iterator) { - mEntities.clear(); - try { - while (iterator.hasNext()) { - mEntities.add(iterator.next()); - } - mHasEntities = true; - } catch (RemoteException e) { - Log.w(TAG, "Problem reading contact data: " + e.toString()); - } - } - - /** * Read from the given {@link Cursor} and build a set of {@link DataStatus} * objects to match any valid statuses found. */ -- 2.11.0