1666ea1b28a76aeba74744148b15099254d918671Owen Lin/* 2666ea1b28a76aeba74744148b15099254d918671Owen Lin * Copyright (C) 2009 The Android Open Source Project 3666ea1b28a76aeba74744148b15099254d918671Owen Lin * 4666ea1b28a76aeba74744148b15099254d918671Owen Lin * Licensed under the Apache License, Version 2.0 (the "License"); 5666ea1b28a76aeba74744148b15099254d918671Owen Lin * you may not use this file except in compliance with the License. 6666ea1b28a76aeba74744148b15099254d918671Owen Lin * You may obtain a copy of the License at 7666ea1b28a76aeba74744148b15099254d918671Owen Lin * 8666ea1b28a76aeba74744148b15099254d918671Owen Lin * http://www.apache.org/licenses/LICENSE-2.0 9666ea1b28a76aeba74744148b15099254d918671Owen Lin * 10666ea1b28a76aeba74744148b15099254d918671Owen Lin * Unless required by applicable law or agreed to in writing, software 11666ea1b28a76aeba74744148b15099254d918671Owen Lin * distributed under the License is distributed on an "AS IS" BASIS, 12666ea1b28a76aeba74744148b15099254d918671Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13666ea1b28a76aeba74744148b15099254d918671Owen Lin * See the License for the specific language governing permissions and 14666ea1b28a76aeba74744148b15099254d918671Owen Lin * limitations under the License. 15666ea1b28a76aeba74744148b15099254d918671Owen Lin */ 16666ea1b28a76aeba74744148b15099254d918671Owen Lin 17666ea1b28a76aeba74744148b15099254d918671Owen Linpackage com.android.camera; 18666ea1b28a76aeba74744148b15099254d918671Owen Lin 19666ea1b28a76aeba74744148b15099254d918671Owen Linimport com.android.camera.gallery.IImage; 20666ea1b28a76aeba74744148b15099254d918671Owen Linimport com.android.camera.gallery.IImageList; 21666ea1b28a76aeba74744148b15099254d918671Owen Linimport com.android.camera.gallery.VideoObject; 22666ea1b28a76aeba74744148b15099254d918671Owen Lin 23666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.content.ContentResolver; 24666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.graphics.Bitmap; 25666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.os.Handler; 26666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.os.Message; 27666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.os.Process; 28666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.provider.MediaStore; 29666ea1b28a76aeba74744148b15099254d918671Owen Lin 30666ea1b28a76aeba74744148b15099254d918671Owen Lin/* 31666ea1b28a76aeba74744148b15099254d918671Owen Lin * Here's the loading strategy. For any given image, load the thumbnail 32666ea1b28a76aeba74744148b15099254d918671Owen Lin * into memory and post a callback to display the resulting bitmap. 33666ea1b28a76aeba74744148b15099254d918671Owen Lin * 34666ea1b28a76aeba74744148b15099254d918671Owen Lin * Then proceed to load the full image bitmap. Three things can 35666ea1b28a76aeba74744148b15099254d918671Owen Lin * happen at this point: 36666ea1b28a76aeba74744148b15099254d918671Owen Lin * 37666ea1b28a76aeba74744148b15099254d918671Owen Lin * 1. the image fails to load because the UI thread decided 38666ea1b28a76aeba74744148b15099254d918671Owen Lin * to move on to a different image. This "cancellation" happens 39666ea1b28a76aeba74744148b15099254d918671Owen Lin * by virtue of the UI thread closing the stream containing the 40666ea1b28a76aeba74744148b15099254d918671Owen Lin * image being decoded. BitmapFactory.decodeStream returns null 41666ea1b28a76aeba74744148b15099254d918671Owen Lin * in this case. 42666ea1b28a76aeba74744148b15099254d918671Owen Lin * 43666ea1b28a76aeba74744148b15099254d918671Owen Lin * 2. the image loaded successfully. At that point we post 44666ea1b28a76aeba74744148b15099254d918671Owen Lin * a callback to the UI thread to actually show the bitmap. 45666ea1b28a76aeba74744148b15099254d918671Owen Lin * 46666ea1b28a76aeba74744148b15099254d918671Owen Lin * 3. when the post runs it checks to see if the image that was 47666ea1b28a76aeba74744148b15099254d918671Owen Lin * loaded is still the one we want. The UI may have moved on 48666ea1b28a76aeba74744148b15099254d918671Owen Lin * to some other image and if so we just drop the newly loaded 49666ea1b28a76aeba74744148b15099254d918671Owen Lin * bitmap on the floor. 50666ea1b28a76aeba74744148b15099254d918671Owen Lin */ 51666ea1b28a76aeba74744148b15099254d918671Owen Lin 52666ea1b28a76aeba74744148b15099254d918671Owen Lininterface ImageGetterCallback { 53666ea1b28a76aeba74744148b15099254d918671Owen Lin public void imageLoaded(int pos, int offset, RotateBitmap bitmap, 54666ea1b28a76aeba74744148b15099254d918671Owen Lin boolean isThumb); 55666ea1b28a76aeba74744148b15099254d918671Owen Lin public boolean wantsThumbnail(int pos, int offset); 56666ea1b28a76aeba74744148b15099254d918671Owen Lin public boolean wantsFullImage(int pos, int offset); 57666ea1b28a76aeba74744148b15099254d918671Owen Lin public int fullImageSizeToUse(int pos, int offset); 58666ea1b28a76aeba74744148b15099254d918671Owen Lin public void completed(); 59666ea1b28a76aeba74744148b15099254d918671Owen Lin public int [] loadOrder(); 60666ea1b28a76aeba74744148b15099254d918671Owen Lin} 61666ea1b28a76aeba74744148b15099254d918671Owen Lin 62666ea1b28a76aeba74744148b15099254d918671Owen Linclass ImageGetter { 63666ea1b28a76aeba74744148b15099254d918671Owen Lin 64666ea1b28a76aeba74744148b15099254d918671Owen Lin @SuppressWarnings("unused") 65666ea1b28a76aeba74744148b15099254d918671Owen Lin private static final String TAG = "ImageGetter"; 66666ea1b28a76aeba74744148b15099254d918671Owen Lin 67666ea1b28a76aeba74744148b15099254d918671Owen Lin // The thread which does the work. 68666ea1b28a76aeba74744148b15099254d918671Owen Lin private Thread mGetterThread; 69666ea1b28a76aeba74744148b15099254d918671Owen Lin 70666ea1b28a76aeba74744148b15099254d918671Owen Lin // The current request serial number. 71666ea1b28a76aeba74744148b15099254d918671Owen Lin // This is increased by one each time a new job is assigned. 72666ea1b28a76aeba74744148b15099254d918671Owen Lin // It is only written in the main thread. 73666ea1b28a76aeba74744148b15099254d918671Owen Lin private int mCurrentSerial; 74666ea1b28a76aeba74744148b15099254d918671Owen Lin 75666ea1b28a76aeba74744148b15099254d918671Owen Lin // The base position that's being retrieved. The actual images retrieved 76666ea1b28a76aeba74744148b15099254d918671Owen Lin // are this base plus each of the offets. -1 means there is no current 77666ea1b28a76aeba74744148b15099254d918671Owen Lin // request needs to be finished. 78666ea1b28a76aeba74744148b15099254d918671Owen Lin private int mCurrentPosition = -1; 79666ea1b28a76aeba74744148b15099254d918671Owen Lin 80666ea1b28a76aeba74744148b15099254d918671Owen Lin // The callback to invoke for each image. 81666ea1b28a76aeba74744148b15099254d918671Owen Lin private ImageGetterCallback mCB; 82666ea1b28a76aeba74744148b15099254d918671Owen Lin 83666ea1b28a76aeba74744148b15099254d918671Owen Lin // The image list for the images. 84666ea1b28a76aeba74744148b15099254d918671Owen Lin private IImageList mImageList; 85666ea1b28a76aeba74744148b15099254d918671Owen Lin 86666ea1b28a76aeba74744148b15099254d918671Owen Lin // The handler to do callback. 87666ea1b28a76aeba74744148b15099254d918671Owen Lin private GetterHandler mHandler; 88666ea1b28a76aeba74744148b15099254d918671Owen Lin 89666ea1b28a76aeba74744148b15099254d918671Owen Lin // True if we want to cancel the current loading. 90666ea1b28a76aeba74744148b15099254d918671Owen Lin private volatile boolean mCancel = true; 91666ea1b28a76aeba74744148b15099254d918671Owen Lin 92666ea1b28a76aeba74744148b15099254d918671Owen Lin // True if the getter thread is idle waiting. 93666ea1b28a76aeba74744148b15099254d918671Owen Lin private boolean mIdle = false; 94666ea1b28a76aeba74744148b15099254d918671Owen Lin 95666ea1b28a76aeba74744148b15099254d918671Owen Lin // True when the getter thread should exit. 96666ea1b28a76aeba74744148b15099254d918671Owen Lin private boolean mDone = false; 97666ea1b28a76aeba74744148b15099254d918671Owen Lin 98666ea1b28a76aeba74744148b15099254d918671Owen Lin private ContentResolver mCr; 99666ea1b28a76aeba74744148b15099254d918671Owen Lin 100666ea1b28a76aeba74744148b15099254d918671Owen Lin private class ImageGetterRunnable implements Runnable { 101666ea1b28a76aeba74744148b15099254d918671Owen Lin 102666ea1b28a76aeba74744148b15099254d918671Owen Lin private Runnable callback(final int position, final int offset, 103666ea1b28a76aeba74744148b15099254d918671Owen Lin final boolean isThumb, 104666ea1b28a76aeba74744148b15099254d918671Owen Lin final RotateBitmap bitmap, 105666ea1b28a76aeba74744148b15099254d918671Owen Lin final int requestSerial) { 106666ea1b28a76aeba74744148b15099254d918671Owen Lin return new Runnable() { 107666ea1b28a76aeba74744148b15099254d918671Owen Lin public void run() { 108666ea1b28a76aeba74744148b15099254d918671Owen Lin // check for inflight callbacks that aren't applicable 109666ea1b28a76aeba74744148b15099254d918671Owen Lin // any longer before delivering them 110666ea1b28a76aeba74744148b15099254d918671Owen Lin if (requestSerial == mCurrentSerial) { 111666ea1b28a76aeba74744148b15099254d918671Owen Lin mCB.imageLoaded(position, offset, bitmap, isThumb); 112666ea1b28a76aeba74744148b15099254d918671Owen Lin } else if (bitmap != null) { 113666ea1b28a76aeba74744148b15099254d918671Owen Lin bitmap.recycle(); 114666ea1b28a76aeba74744148b15099254d918671Owen Lin } 115666ea1b28a76aeba74744148b15099254d918671Owen Lin } 116666ea1b28a76aeba74744148b15099254d918671Owen Lin }; 117666ea1b28a76aeba74744148b15099254d918671Owen Lin } 118666ea1b28a76aeba74744148b15099254d918671Owen Lin 119666ea1b28a76aeba74744148b15099254d918671Owen Lin private Runnable completedCallback(final int requestSerial) { 120666ea1b28a76aeba74744148b15099254d918671Owen Lin return new Runnable() { 121666ea1b28a76aeba74744148b15099254d918671Owen Lin public void run() { 122666ea1b28a76aeba74744148b15099254d918671Owen Lin if (requestSerial == mCurrentSerial) { 123666ea1b28a76aeba74744148b15099254d918671Owen Lin mCB.completed(); 124666ea1b28a76aeba74744148b15099254d918671Owen Lin } 125666ea1b28a76aeba74744148b15099254d918671Owen Lin } 126666ea1b28a76aeba74744148b15099254d918671Owen Lin }; 127666ea1b28a76aeba74744148b15099254d918671Owen Lin } 128666ea1b28a76aeba74744148b15099254d918671Owen Lin 129666ea1b28a76aeba74744148b15099254d918671Owen Lin public void run() { 130666ea1b28a76aeba74744148b15099254d918671Owen Lin // Lower the priority of this thread to avoid competing with 131666ea1b28a76aeba74744148b15099254d918671Owen Lin // the UI thread. 132666ea1b28a76aeba74744148b15099254d918671Owen Lin Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 133666ea1b28a76aeba74744148b15099254d918671Owen Lin 134666ea1b28a76aeba74744148b15099254d918671Owen Lin while (true) { 135666ea1b28a76aeba74744148b15099254d918671Owen Lin synchronized (ImageGetter.this) { 136666ea1b28a76aeba74744148b15099254d918671Owen Lin while (mCancel || mDone || mCurrentPosition == -1) { 137666ea1b28a76aeba74744148b15099254d918671Owen Lin if (mDone) return; 138666ea1b28a76aeba74744148b15099254d918671Owen Lin mIdle = true; 139666ea1b28a76aeba74744148b15099254d918671Owen Lin ImageGetter.this.notify(); 140666ea1b28a76aeba74744148b15099254d918671Owen Lin try { 141666ea1b28a76aeba74744148b15099254d918671Owen Lin ImageGetter.this.wait(); 142666ea1b28a76aeba74744148b15099254d918671Owen Lin } catch (InterruptedException ex) { 143666ea1b28a76aeba74744148b15099254d918671Owen Lin // ignore 144666ea1b28a76aeba74744148b15099254d918671Owen Lin } 145666ea1b28a76aeba74744148b15099254d918671Owen Lin mIdle = false; 146666ea1b28a76aeba74744148b15099254d918671Owen Lin } 147666ea1b28a76aeba74744148b15099254d918671Owen Lin } 148666ea1b28a76aeba74744148b15099254d918671Owen Lin 149666ea1b28a76aeba74744148b15099254d918671Owen Lin executeRequest(); 150666ea1b28a76aeba74744148b15099254d918671Owen Lin 151666ea1b28a76aeba74744148b15099254d918671Owen Lin synchronized (ImageGetter.this) { 152666ea1b28a76aeba74744148b15099254d918671Owen Lin mCurrentPosition = -1; 153666ea1b28a76aeba74744148b15099254d918671Owen Lin } 154666ea1b28a76aeba74744148b15099254d918671Owen Lin } 155666ea1b28a76aeba74744148b15099254d918671Owen Lin } 156666ea1b28a76aeba74744148b15099254d918671Owen Lin private void executeRequest() { 157666ea1b28a76aeba74744148b15099254d918671Owen Lin int imageCount = mImageList.getCount(); 158666ea1b28a76aeba74744148b15099254d918671Owen Lin 159666ea1b28a76aeba74744148b15099254d918671Owen Lin int [] order = mCB.loadOrder(); 160666ea1b28a76aeba74744148b15099254d918671Owen Lin for (int i = 0; i < order.length; i++) { 161666ea1b28a76aeba74744148b15099254d918671Owen Lin if (mCancel) return; 162666ea1b28a76aeba74744148b15099254d918671Owen Lin int offset = order[i]; 163666ea1b28a76aeba74744148b15099254d918671Owen Lin int imageNumber = mCurrentPosition + offset; 164666ea1b28a76aeba74744148b15099254d918671Owen Lin if (imageNumber >= 0 && imageNumber < imageCount) { 165666ea1b28a76aeba74744148b15099254d918671Owen Lin if (!mCB.wantsThumbnail(mCurrentPosition, offset)) { 166666ea1b28a76aeba74744148b15099254d918671Owen Lin continue; 167666ea1b28a76aeba74744148b15099254d918671Owen Lin } 168666ea1b28a76aeba74744148b15099254d918671Owen Lin 169666ea1b28a76aeba74744148b15099254d918671Owen Lin IImage image = mImageList.getImageAt(imageNumber); 170666ea1b28a76aeba74744148b15099254d918671Owen Lin if (image == null) continue; 171666ea1b28a76aeba74744148b15099254d918671Owen Lin if (mCancel) return; 172666ea1b28a76aeba74744148b15099254d918671Owen Lin 173666ea1b28a76aeba74744148b15099254d918671Owen Lin Bitmap b = image.thumbBitmap(IImage.NO_ROTATE); 174666ea1b28a76aeba74744148b15099254d918671Owen Lin if (b == null) continue; 175666ea1b28a76aeba74744148b15099254d918671Owen Lin if (mCancel) { 176666ea1b28a76aeba74744148b15099254d918671Owen Lin b.recycle(); 177666ea1b28a76aeba74744148b15099254d918671Owen Lin return; 178666ea1b28a76aeba74744148b15099254d918671Owen Lin } 179666ea1b28a76aeba74744148b15099254d918671Owen Lin 180666ea1b28a76aeba74744148b15099254d918671Owen Lin Runnable cb = callback(mCurrentPosition, offset, 181666ea1b28a76aeba74744148b15099254d918671Owen Lin true, 182666ea1b28a76aeba74744148b15099254d918671Owen Lin new RotateBitmap(b, image.getDegreesRotated()), 183666ea1b28a76aeba74744148b15099254d918671Owen Lin mCurrentSerial); 184666ea1b28a76aeba74744148b15099254d918671Owen Lin mHandler.postGetterCallback(cb); 185666ea1b28a76aeba74744148b15099254d918671Owen Lin } 186666ea1b28a76aeba74744148b15099254d918671Owen Lin } 187666ea1b28a76aeba74744148b15099254d918671Owen Lin 188666ea1b28a76aeba74744148b15099254d918671Owen Lin for (int i = 0; i < order.length; i++) { 189666ea1b28a76aeba74744148b15099254d918671Owen Lin if (mCancel) return; 190666ea1b28a76aeba74744148b15099254d918671Owen Lin int offset = order[i]; 191666ea1b28a76aeba74744148b15099254d918671Owen Lin int imageNumber = mCurrentPosition + offset; 192666ea1b28a76aeba74744148b15099254d918671Owen Lin if (imageNumber >= 0 && imageNumber < imageCount) { 193666ea1b28a76aeba74744148b15099254d918671Owen Lin if (!mCB.wantsFullImage(mCurrentPosition, offset)) { 194666ea1b28a76aeba74744148b15099254d918671Owen Lin continue; 195666ea1b28a76aeba74744148b15099254d918671Owen Lin } 196666ea1b28a76aeba74744148b15099254d918671Owen Lin 197666ea1b28a76aeba74744148b15099254d918671Owen Lin IImage image = mImageList.getImageAt(imageNumber); 198666ea1b28a76aeba74744148b15099254d918671Owen Lin if (image == null) continue; 199666ea1b28a76aeba74744148b15099254d918671Owen Lin if (image instanceof VideoObject) continue; 200666ea1b28a76aeba74744148b15099254d918671Owen Lin if (mCancel) return; 201666ea1b28a76aeba74744148b15099254d918671Owen Lin 202666ea1b28a76aeba74744148b15099254d918671Owen Lin int sizeToUse = mCB.fullImageSizeToUse( 203666ea1b28a76aeba74744148b15099254d918671Owen Lin mCurrentPosition, offset); 204666ea1b28a76aeba74744148b15099254d918671Owen Lin Bitmap b = image.fullSizeBitmap(sizeToUse, 3 * 1024 * 1024, 205666ea1b28a76aeba74744148b15099254d918671Owen Lin IImage.NO_ROTATE, IImage.USE_NATIVE); 206666ea1b28a76aeba74744148b15099254d918671Owen Lin 207666ea1b28a76aeba74744148b15099254d918671Owen Lin if (b == null) continue; 208666ea1b28a76aeba74744148b15099254d918671Owen Lin if (mCancel) { 209666ea1b28a76aeba74744148b15099254d918671Owen Lin b.recycle(); 210666ea1b28a76aeba74744148b15099254d918671Owen Lin return; 211666ea1b28a76aeba74744148b15099254d918671Owen Lin } 212666ea1b28a76aeba74744148b15099254d918671Owen Lin 213666ea1b28a76aeba74744148b15099254d918671Owen Lin RotateBitmap rb = new RotateBitmap(b, 214666ea1b28a76aeba74744148b15099254d918671Owen Lin image.getDegreesRotated()); 215666ea1b28a76aeba74744148b15099254d918671Owen Lin 216666ea1b28a76aeba74744148b15099254d918671Owen Lin Runnable cb = callback(mCurrentPosition, offset, 217666ea1b28a76aeba74744148b15099254d918671Owen Lin false, rb, mCurrentSerial); 218666ea1b28a76aeba74744148b15099254d918671Owen Lin mHandler.postGetterCallback(cb); 219666ea1b28a76aeba74744148b15099254d918671Owen Lin } 220666ea1b28a76aeba74744148b15099254d918671Owen Lin } 221666ea1b28a76aeba74744148b15099254d918671Owen Lin 222666ea1b28a76aeba74744148b15099254d918671Owen Lin mHandler.postGetterCallback(completedCallback(mCurrentSerial)); 223666ea1b28a76aeba74744148b15099254d918671Owen Lin } 224666ea1b28a76aeba74744148b15099254d918671Owen Lin } 225666ea1b28a76aeba74744148b15099254d918671Owen Lin 226666ea1b28a76aeba74744148b15099254d918671Owen Lin public ImageGetter(ContentResolver cr) { 227666ea1b28a76aeba74744148b15099254d918671Owen Lin mCr = cr; 228666ea1b28a76aeba74744148b15099254d918671Owen Lin mGetterThread = new Thread(new ImageGetterRunnable()); 229666ea1b28a76aeba74744148b15099254d918671Owen Lin mGetterThread.setName("ImageGettter"); 230666ea1b28a76aeba74744148b15099254d918671Owen Lin mGetterThread.start(); 231666ea1b28a76aeba74744148b15099254d918671Owen Lin } 232666ea1b28a76aeba74744148b15099254d918671Owen Lin 233666ea1b28a76aeba74744148b15099254d918671Owen Lin // Cancels current loading (without waiting). 234666ea1b28a76aeba74744148b15099254d918671Owen Lin public synchronized void cancelCurrent() { 235666ea1b28a76aeba74744148b15099254d918671Owen Lin Util.Assert(mGetterThread != null); 236666ea1b28a76aeba74744148b15099254d918671Owen Lin mCancel = true; 2378aa3fbcf9a5a0d11acd48861f5167073e3554980Owen Lin BitmapManager.instance().cancelThreadDecoding(mGetterThread, mCr); 238666ea1b28a76aeba74744148b15099254d918671Owen Lin } 239666ea1b28a76aeba74744148b15099254d918671Owen Lin 240666ea1b28a76aeba74744148b15099254d918671Owen Lin // Cancels current loading (with waiting). 241666ea1b28a76aeba74744148b15099254d918671Owen Lin private synchronized void cancelCurrentAndWait() { 242666ea1b28a76aeba74744148b15099254d918671Owen Lin cancelCurrent(); 243666ea1b28a76aeba74744148b15099254d918671Owen Lin while (mIdle != true) { 244666ea1b28a76aeba74744148b15099254d918671Owen Lin try { 245666ea1b28a76aeba74744148b15099254d918671Owen Lin wait(); 246666ea1b28a76aeba74744148b15099254d918671Owen Lin } catch (InterruptedException ex) { 247666ea1b28a76aeba74744148b15099254d918671Owen Lin // ignore. 248666ea1b28a76aeba74744148b15099254d918671Owen Lin } 249666ea1b28a76aeba74744148b15099254d918671Owen Lin } 250666ea1b28a76aeba74744148b15099254d918671Owen Lin } 251666ea1b28a76aeba74744148b15099254d918671Owen Lin 252666ea1b28a76aeba74744148b15099254d918671Owen Lin // Stops this image getter. 253666ea1b28a76aeba74744148b15099254d918671Owen Lin public void stop() { 254666ea1b28a76aeba74744148b15099254d918671Owen Lin synchronized (this) { 255666ea1b28a76aeba74744148b15099254d918671Owen Lin cancelCurrentAndWait(); 256666ea1b28a76aeba74744148b15099254d918671Owen Lin mDone = true; 257666ea1b28a76aeba74744148b15099254d918671Owen Lin notify(); 258666ea1b28a76aeba74744148b15099254d918671Owen Lin } 259666ea1b28a76aeba74744148b15099254d918671Owen Lin try { 260666ea1b28a76aeba74744148b15099254d918671Owen Lin mGetterThread.join(); 261666ea1b28a76aeba74744148b15099254d918671Owen Lin } catch (InterruptedException ex) { 262666ea1b28a76aeba74744148b15099254d918671Owen Lin // Ignore the exception 263666ea1b28a76aeba74744148b15099254d918671Owen Lin } 264666ea1b28a76aeba74744148b15099254d918671Owen Lin mGetterThread = null; 265666ea1b28a76aeba74744148b15099254d918671Owen Lin } 266666ea1b28a76aeba74744148b15099254d918671Owen Lin 267666ea1b28a76aeba74744148b15099254d918671Owen Lin public synchronized void setPosition(int position, ImageGetterCallback cb, 268666ea1b28a76aeba74744148b15099254d918671Owen Lin IImageList imageList, GetterHandler handler) { 269666ea1b28a76aeba74744148b15099254d918671Owen Lin // Cancel the previous request. 270666ea1b28a76aeba74744148b15099254d918671Owen Lin cancelCurrentAndWait(); 271666ea1b28a76aeba74744148b15099254d918671Owen Lin 272666ea1b28a76aeba74744148b15099254d918671Owen Lin // Set new data. 273666ea1b28a76aeba74744148b15099254d918671Owen Lin mCurrentPosition = position; 274666ea1b28a76aeba74744148b15099254d918671Owen Lin mCB = cb; 275666ea1b28a76aeba74744148b15099254d918671Owen Lin mImageList = imageList; 276666ea1b28a76aeba74744148b15099254d918671Owen Lin mHandler = handler; 277666ea1b28a76aeba74744148b15099254d918671Owen Lin mCurrentSerial += 1; 278666ea1b28a76aeba74744148b15099254d918671Owen Lin 279666ea1b28a76aeba74744148b15099254d918671Owen Lin // Kick-start the current request. 280666ea1b28a76aeba74744148b15099254d918671Owen Lin mCancel = false; 281666ea1b28a76aeba74744148b15099254d918671Owen Lin BitmapManager.instance().allowThreadDecoding(mGetterThread); 282666ea1b28a76aeba74744148b15099254d918671Owen Lin notify(); 283666ea1b28a76aeba74744148b15099254d918671Owen Lin } 284666ea1b28a76aeba74744148b15099254d918671Owen Lin} 285666ea1b28a76aeba74744148b15099254d918671Owen Lin 286666ea1b28a76aeba74744148b15099254d918671Owen Linclass GetterHandler extends Handler { 287666ea1b28a76aeba74744148b15099254d918671Owen Lin private static final int IMAGE_GETTER_CALLBACK = 1; 288666ea1b28a76aeba74744148b15099254d918671Owen Lin 289666ea1b28a76aeba74744148b15099254d918671Owen Lin @Override 290666ea1b28a76aeba74744148b15099254d918671Owen Lin public void handleMessage(Message message) { 291666ea1b28a76aeba74744148b15099254d918671Owen Lin switch(message.what) { 292666ea1b28a76aeba74744148b15099254d918671Owen Lin case IMAGE_GETTER_CALLBACK: 293666ea1b28a76aeba74744148b15099254d918671Owen Lin ((Runnable) message.obj).run(); 294666ea1b28a76aeba74744148b15099254d918671Owen Lin break; 295666ea1b28a76aeba74744148b15099254d918671Owen Lin } 296666ea1b28a76aeba74744148b15099254d918671Owen Lin } 297666ea1b28a76aeba74744148b15099254d918671Owen Lin 298666ea1b28a76aeba74744148b15099254d918671Owen Lin public void postGetterCallback(Runnable callback) { 299666ea1b28a76aeba74744148b15099254d918671Owen Lin postDelayedGetterCallback(callback, 0); 300666ea1b28a76aeba74744148b15099254d918671Owen Lin } 301666ea1b28a76aeba74744148b15099254d918671Owen Lin 302666ea1b28a76aeba74744148b15099254d918671Owen Lin public void postDelayedGetterCallback(Runnable callback, long delay) { 303666ea1b28a76aeba74744148b15099254d918671Owen Lin if (callback == null) { 304666ea1b28a76aeba74744148b15099254d918671Owen Lin throw new NullPointerException(); 305666ea1b28a76aeba74744148b15099254d918671Owen Lin } 306666ea1b28a76aeba74744148b15099254d918671Owen Lin Message message = Message.obtain(); 307666ea1b28a76aeba74744148b15099254d918671Owen Lin message.what = IMAGE_GETTER_CALLBACK; 308666ea1b28a76aeba74744148b15099254d918671Owen Lin message.obj = callback; 309666ea1b28a76aeba74744148b15099254d918671Owen Lin sendMessageDelayed(message, delay); 310666ea1b28a76aeba74744148b15099254d918671Owen Lin } 311666ea1b28a76aeba74744148b15099254d918671Owen Lin 312666ea1b28a76aeba74744148b15099254d918671Owen Lin public void removeAllGetterCallbacks() { 313666ea1b28a76aeba74744148b15099254d918671Owen Lin removeMessages(IMAGE_GETTER_CALLBACK); 314666ea1b28a76aeba74744148b15099254d918671Owen Lin } 315666ea1b28a76aeba74744148b15099254d918671Owen Lin} 316