1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.gallery3d.ui; 18 19 import android.graphics.Bitmap; 20 21 import com.android.photos.data.GalleryBitmapPool; 22 import com.android.gallery3d.util.Future; 23 import com.android.gallery3d.util.FutureListener; 24 25 // We use this class to 26 // 1.) load bitmaps in background. 27 // 2.) as a place holder for the loaded bitmap 28 public abstract class BitmapLoader implements FutureListener<Bitmap> { 29 @SuppressWarnings("unused") 30 private static final String TAG = "BitmapLoader"; 31 32 /* Transition Map: 33 * INIT -> REQUESTED, RECYCLED 34 * REQUESTED -> INIT (cancel), LOADED, ERROR, RECYCLED 35 * LOADED, ERROR -> RECYCLED 36 */ 37 private static final int STATE_INIT = 0; 38 private static final int STATE_REQUESTED = 1; 39 private static final int STATE_LOADED = 2; 40 private static final int STATE_ERROR = 3; 41 private static final int STATE_RECYCLED = 4; 42 43 private int mState = STATE_INIT; 44 // mTask is not null only when a task is on the way 45 private Future<Bitmap> mTask; 46 private Bitmap mBitmap; 47 48 @Override onFutureDone(Future<Bitmap> future)49 public void onFutureDone(Future<Bitmap> future) { 50 synchronized (this) { 51 mTask = null; 52 mBitmap = future.get(); 53 if (mState == STATE_RECYCLED) { 54 if (mBitmap != null) { 55 GalleryBitmapPool.getInstance().put(mBitmap); 56 mBitmap = null; 57 } 58 return; // don't call callback 59 } 60 if (future.isCancelled() && mBitmap == null) { 61 if (mState == STATE_REQUESTED) mTask = submitBitmapTask(this); 62 return; // don't call callback 63 } else { 64 mState = mBitmap == null ? STATE_ERROR : STATE_LOADED; 65 } 66 } 67 onLoadComplete(mBitmap); 68 } 69 startLoad()70 public synchronized void startLoad() { 71 if (mState == STATE_INIT) { 72 mState = STATE_REQUESTED; 73 if (mTask == null) mTask = submitBitmapTask(this); 74 } 75 } 76 cancelLoad()77 public synchronized void cancelLoad() { 78 if (mState == STATE_REQUESTED) { 79 mState = STATE_INIT; 80 if (mTask != null) mTask.cancel(); 81 } 82 } 83 84 // Recycle the loader and the bitmap recycle()85 public synchronized void recycle() { 86 mState = STATE_RECYCLED; 87 if (mBitmap != null) { 88 GalleryBitmapPool.getInstance().put(mBitmap); 89 mBitmap = null; 90 } 91 if (mTask != null) mTask.cancel(); 92 } 93 isRequestInProgress()94 public synchronized boolean isRequestInProgress() { 95 return mState == STATE_REQUESTED; 96 } 97 isRecycled()98 public synchronized boolean isRecycled() { 99 return mState == STATE_RECYCLED; 100 } 101 getBitmap()102 public synchronized Bitmap getBitmap() { 103 return mBitmap; 104 } 105 submitBitmapTask(FutureListener<Bitmap> l)106 abstract protected Future<Bitmap> submitBitmapTask(FutureListener<Bitmap> l); onLoadComplete(Bitmap bitmap)107 abstract protected void onLoadComplete(Bitmap bitmap); 108 } 109