11cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein/*
21cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * Copyright (C) 2011 Google Inc.
31cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * Licensed to The Android Open Source Project.
41cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein *
51cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * Licensed under the Apache License, Version 2.0 (the "License");
61cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * you may not use this file except in compliance with the License.
71cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * You may obtain a copy of the License at
81cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein *
91cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein *      http://www.apache.org/licenses/LICENSE-2.0
101cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein *
111cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * Unless required by applicable law or agreed to in writing, software
121cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * distributed under the License is distributed on an "AS IS" BASIS,
131cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
141cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * See the License for the specific language governing permissions and
151cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * limitations under the License.
161cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein */
171cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
181cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinpackage com.android.ex.photo.loaders;
191cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
201cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.content.AsyncTaskLoader;
211cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.content.ContentResolver;
221cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.content.Context;
231cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.graphics.Bitmap;
241cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.net.Uri;
254f38cc1673163848c7b843cb9d23b21945b0bf82Mark Weiimport android.util.DisplayMetrics;
261cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
271cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport com.android.ex.photo.fragments.PhotoViewFragment;
281cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport com.android.ex.photo.util.ImageUtils;
291cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
301cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein/**
311cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * Loader for the bitmap of a photo.
321cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein */
331cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinpublic class PhotoBitmapLoader extends AsyncTaskLoader<Bitmap> {
34a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein    private String mPhotoUri;
351cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
361cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    private Bitmap mBitmap;
371cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
381cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    public PhotoBitmapLoader(Context context, String photoUri) {
391cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        super(context);
401cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        mPhotoUri = photoUri;
411cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
421cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
43a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein    public void setPhotoUri(String photoUri) {
44a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein        mPhotoUri = photoUri;
45a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein    }
46a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein
471cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    @Override
481cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    public Bitmap loadInBackground() {
491cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        Context context = getContext();
501cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
511cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        if (context != null && mPhotoUri != null) {
521cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            final ContentResolver resolver = context.getContentResolver();
534f38cc1673163848c7b843cb9d23b21945b0bf82Mark Wei            Bitmap bitmap = ImageUtils.createLocalBitmap(resolver, Uri.parse(mPhotoUri),
541cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein                    PhotoViewFragment.sPhotoSize);
55a7e22413eb860a1d9ffb46221c63e29ba7330ff5Mark Wei            if (bitmap != null) {
56a7e22413eb860a1d9ffb46221c63e29ba7330ff5Mark Wei                bitmap.setDensity(DisplayMetrics.DENSITY_MEDIUM);
57a7e22413eb860a1d9ffb46221c63e29ba7330ff5Mark Wei            }
584f38cc1673163848c7b843cb9d23b21945b0bf82Mark Wei            return bitmap;
591cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        }
601cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
611cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        return null;
621cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
631cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
641cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    /**
651cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein     * Called when there is new data to deliver to the client.  The
661cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein     * super class will take care of delivering it; the implementation
671cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein     * here just adds a little more logic.
681cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein     */
691cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    @Override
701cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    public void deliverResult(Bitmap bitmap) {
711cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        if (isReset()) {
721cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            // An async query came in while the loader is stopped.  We
731cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            // don't need the result.
741cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            if (bitmap != null) {
751cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein                onReleaseResources(bitmap);
761cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            }
771cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        }
781cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        Bitmap oldBitmap = mBitmap;
791cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        mBitmap = bitmap;
801cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
811cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        if (isStarted()) {
821cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            // If the Loader is currently started, we can immediately
831cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            // deliver its results.
841cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            super.deliverResult(bitmap);
851cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        }
861cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
871cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        // At this point we can release the resources associated with
881cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        // 'oldBitmap' if needed; now that the new result is delivered we
891cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        // know that it is no longer in use.
901cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        if (oldBitmap != null && oldBitmap != bitmap && !oldBitmap.isRecycled()) {
911cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            onReleaseResources(oldBitmap);
921cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        }
931cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
941cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
951cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    /**
961cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein     * Handles a request to start the Loader.
971cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein     */
981cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    @Override
991cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    protected void onStartLoading() {
1001cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        if (mBitmap != null) {
1011cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            // If we currently have a result available, deliver it
1021cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            // immediately.
1031cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            deliverResult(mBitmap);
1041cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        }
1051cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
1061cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        if (takeContentChanged() || mBitmap == null) {
1071cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            // If the data has changed since the last time it was loaded
1081cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            // or is not currently available, start a load.
1091cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            forceLoad();
1101cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        }
1111cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
1121cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
1131cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    /**
1141cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein     * Handles a request to stop the Loader.
1151cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein     */
1161cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    @Override protected void onStopLoading() {
1171cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        // Attempt to cancel the current load task if possible.
1181cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        cancelLoad();
1191cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
1201cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
1211cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    /**
1221cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein     * Handles a request to cancel a load.
1231cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein     */
1241cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    @Override
1251cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    public void onCanceled(Bitmap bitmap) {
1261cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        super.onCanceled(bitmap);
1271cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
1281cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        // At this point we can release the resources associated with 'bitmap'
1291cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        // if needed.
1301cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        onReleaseResources(bitmap);
1311cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
1321cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
1331cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    /**
1341cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein     * Handles a request to completely reset the Loader.
1351cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein     */
1361cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    @Override
1371cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    protected void onReset() {
1381cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        super.onReset();
1391cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
1401cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        // Ensure the loader is stopped
1411cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        onStopLoading();
1421cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
1431cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        // At this point we can release the resources associated with 'bitmap'
1441cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        // if needed.
1451cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        if (mBitmap != null) {
1461cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            onReleaseResources(mBitmap);
1471cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            mBitmap = null;
1481cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        }
1491cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
1501cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
1511cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    /**
1521cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein     * Helper function to take care of releasing resources associated
1531cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein     * with an actively loaded data set.
1541cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein     */
1551cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    protected void onReleaseResources(Bitmap bitmap) {
1561cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        if (bitmap != null && !bitmap.isRecycled()) {
1571cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            bitmap.recycle();
1581cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        }
1591cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
1601cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein}
161