11a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin/*
21a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin * Copyright (C) 2010 The Android Open Source Project
31a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin *
41a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin * Licensed under the Apache License, Version 2.0 (the "License");
51a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin * you may not use this file except in compliance with the License.
61a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin * You may obtain a copy of the License at
71a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin *
81a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin *      http://www.apache.org/licenses/LICENSE-2.0
91a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin *
101a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin * Unless required by applicable law or agreed to in writing, software
111a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin * distributed under the License is distributed on an "AS IS" BASIS,
121a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin * See the License for the specific language governing permissions and
141a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin * limitations under the License.
151a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin */
161a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
171a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Linpackage com.android.gallery3d.ui;
181a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
191a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Linimport android.graphics.Bitmap;
201a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
21f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescuimport com.android.photos.data.GalleryBitmapPool;
221a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Linimport com.android.gallery3d.util.Future;
231a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Linimport com.android.gallery3d.util.FutureListener;
241a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
251a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin// We use this class to
261a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin//     1.) load bitmaps in background.
271a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin//     2.) as a place holder for the loaded bitmap
281a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Linpublic abstract class BitmapLoader implements FutureListener<Bitmap> {
291a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    @SuppressWarnings("unused")
301a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private static final String TAG = "BitmapLoader";
311a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
321a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    /* Transition Map:
331a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin     *   INIT -> REQUESTED, RECYCLED
341a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin     *   REQUESTED -> INIT (cancel), LOADED, ERROR, RECYCLED
351a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin     *   LOADED, ERROR -> RECYCLED
361a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin     */
371a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private static final int STATE_INIT = 0;
381a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private static final int STATE_REQUESTED = 1;
391a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private static final int STATE_LOADED = 2;
401a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private static final int STATE_ERROR = 3;
411a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private static final int STATE_RECYCLED = 4;
421a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
431a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private int mState = STATE_INIT;
441a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    // mTask is not null only when a task is on the way
451a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private Future<Bitmap> mTask;
461a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private Bitmap mBitmap;
471a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
481a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    @Override
491a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    public void onFutureDone(Future<Bitmap> future) {
501a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        synchronized (this) {
511a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            mTask = null;
521a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            mBitmap = future.get();
531a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            if (mState == STATE_RECYCLED) {
541a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                if (mBitmap != null) {
55f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu                    GalleryBitmapPool.getInstance().put(mBitmap);
561a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                    mBitmap = null;
571a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                }
581a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                return; // don't call callback
591a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            }
601a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            if (future.isCancelled() && mBitmap == null) {
611a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                if (mState == STATE_REQUESTED) mTask = submitBitmapTask(this);
621a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                return; // don't call callback
631a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            } else {
641a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                mState = mBitmap == null ? STATE_ERROR : STATE_LOADED;
651a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            }
661a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        }
671a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        onLoadComplete(mBitmap);
681a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    }
691a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
701a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    public synchronized void startLoad() {
711a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        if (mState == STATE_INIT) {
721a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            mState = STATE_REQUESTED;
731a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            if (mTask == null) mTask = submitBitmapTask(this);
741a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        }
751a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    }
761a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
771a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    public synchronized void cancelLoad() {
781a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        if (mState == STATE_REQUESTED) {
791a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            mState = STATE_INIT;
801a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            if (mTask != null) mTask.cancel();
811a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        }
821a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    }
831a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
841a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    // Recycle the loader and the bitmap
851a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    public synchronized void recycle() {
861a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        mState = STATE_RECYCLED;
871a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        if (mBitmap != null) {
88f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu            GalleryBitmapPool.getInstance().put(mBitmap);
891a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            mBitmap = null;
901a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        }
911a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        if (mTask != null) mTask.cancel();
921a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    }
931a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
941a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    public synchronized boolean isRequestInProgress() {
951a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        return mState == STATE_REQUESTED;
961a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    }
971a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
981a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    public synchronized boolean isRecycled() {
991a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        return mState == STATE_RECYCLED;
1001a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    }
1011a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
1021a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    public synchronized Bitmap getBitmap() {
1031a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        return mBitmap;
1041a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    }
1051a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
1061a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    abstract protected Future<Bitmap> submitBitmapTask(FutureListener<Bitmap> l);
1071a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    abstract protected void onLoadComplete(Bitmap bitmap);
1081a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin}
109