OSDN Git Service

Use a thread pool to fetch images. Bug 2163087.
authorCostin Manolache <costin@google.com>
Tue, 6 Oct 2009 19:22:09 +0000 (12:22 -0700)
committerCostin Manolache <costin@google.com>
Tue, 6 Oct 2009 19:22:09 +0000 (12:22 -0700)
src/com/android/contacts/ContactsListActivity.java

index c4ef60f..78ab07e 100644 (file)
@@ -111,6 +111,9 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
 
 /*TODO(emillar) I commented most of the code that deals with modes and filtering. It should be
  * brought back in as we add back that functionality.
@@ -389,6 +392,8 @@ public class ContactsListActivity extends ListActivity implements
     private static final int CONTACTS_ID = 1001;
     private static final UriMatcher sContactsIdMatcher;
 
+    private static ExecutorService sImageFetchThreadPool;
+
     static {
         sContactsIdMatcher = new UriMatcher(UriMatcher.NO_MATCH);
         sContactsIdMatcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID);
@@ -2021,6 +2026,7 @@ public class ContactsListActivity extends ListActivity implements
         private Cursor mSuggestionsCursor;
         private int mSuggestionsCursorCount;
         private ImageFetchHandler mHandler;
+        private ImageDbFetcher mImageFetcher;
         private static final int FETCH_IMAGE_MSG = 1;
 
         public ContactItemListAdapter(Context context) {
@@ -2095,18 +2101,11 @@ public class ContactsListActivity extends ListActivity implements
                             break;
                         }
 
-                        Bitmap photo = null;
-                        try {
-                            photo = ContactsUtils.loadContactPhoto(mContext, photoId, null);
-                        } catch (OutOfMemoryError e) {
-                            // Not enough memory for the photo, do nothing.
-                        }
+                        Bitmap photo = mBitmapCache.get(photoId).get();
                         if (photo == null) {
                             break;
                         }
 
-                        mBitmapCache.put(photoId, new SoftReference<Bitmap>(photo));
-
                         // Make sure the photoId on this image view has not changed
                         // while we were loading the image.
                         synchronized (imageView) {
@@ -2127,6 +2126,50 @@ public class ContactsListActivity extends ListActivity implements
             }
         }
 
+        private class ImageDbFetcher implements Runnable {
+            long mPhotoId;
+            private ImageView mImageView;
+
+            public ImageDbFetcher(long photoId, ImageView imageView) {
+                this.mPhotoId = photoId;
+                this.mImageView = imageView;
+            }
+
+            public void run() {
+                if (ContactsListActivity.this.isFinishing()) {
+                    return;
+                }
+
+                if (Thread.currentThread().interrupted()) {
+                    // shutdown has been called.
+                    return;
+                }
+                Bitmap photo = null;
+                try {
+                    photo = ContactsUtils.loadContactPhoto(mContext, mPhotoId, null);
+                } catch (OutOfMemoryError e) {
+                    // Not enough memory for the photo, do nothing.
+                }
+
+                if (photo == null) {
+                    return;
+                }
+
+                mBitmapCache.put(mPhotoId, new SoftReference<Bitmap>(photo));
+
+                if (Thread.currentThread().interrupted()) {
+                    // shutdown has been called.
+                    return;
+                }
+
+                // Update must happen on UI thread
+                Message msg = new Message();
+                msg.what = FETCH_IMAGE_MSG;
+                msg.obj = mImageView;
+                mHandler.sendMessage(msg);
+            }
+        }
+
         public void setSuggestionsCursor(Cursor cursor) {
             if (mSuggestionsCursor != null) {
                 mSuggestionsCursor.close();
@@ -2775,14 +2818,42 @@ public class ContactsListActivity extends ListActivity implements
         }
 
         private void sendFetchImageMessage(ImageView view) {
-            Message msg = new Message();
-            msg.what = FETCH_IMAGE_MSG;
-            msg.obj = view;
-            mHandler.sendMessage(msg);
+            final PhotoInfo info = (PhotoInfo) view.getTag();
+            if (info == null) {
+                return;
+            }
+            final long photoId = info.photoId;
+            if (photoId == 0) {
+                return;
+            }
+            mImageFetcher = new ImageDbFetcher(photoId, view);
+            synchronized (ContactsListActivity.this) {
+                // can't sync on sImageFetchThreadPool.
+                if (sImageFetchThreadPool == null) {
+                    // Don't use more than 3 threads at a time to update. The thread pool will be
+                    // shared by all contact items.
+                    sImageFetchThreadPool = Executors.newFixedThreadPool(3);
+                }
+                sImageFetchThreadPool.execute(mImageFetcher);
+            }
         }
 
-        /** Clear all pending messages on the {@link ImageFetchHandler} */
+
+        /**
+         * Stop the image fetching for ALL contacts, if one is in progress we'll
+         * not query the database.
+         *
+         * TODO: move this method to ContactsListActivity, it does not apply to the current
+         * contact.
+         */
         public void clearImageFetching() {
+            synchronized (ContactsListActivity.this) {
+                if (sImageFetchThreadPool != null) {
+                    sImageFetchThreadPool.shutdownNow();
+                    sImageFetchThreadPool = null;
+                }
+            }
+
             mHandler.clearImageFecthing();
         }
     }