1f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein/* 2f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Copyright (C) 2011 Google Inc. 3f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Licensed to The Android Open Source Project. 4f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * 5f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Licensed under the Apache License, Version 2.0 (the "License"); 6f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * you may not use this file except in compliance with the License. 7f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * You may obtain a copy of the License at 8f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * 9f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * http://www.apache.org/licenses/LICENSE-2.0 10f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * 11f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Unless required by applicable law or agreed to in writing, software 12f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * distributed under the License is distributed on an "AS IS" BASIS, 13f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * See the License for the specific language governing permissions and 15f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * limitations under the License. 16f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein */ 17f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 18f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinpackage com.android.ex.photo.loaders; 19f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 20f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.content.ContentResolver; 21f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.content.Context; 22f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.graphics.Bitmap; 23f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.net.Uri; 248746927a945358bb9e515985a37cac7807261026Martin Hibdonimport android.support.v4.content.AsyncTaskLoader; 253a14814364ff1e48109d32a06bd063c66914889bMark Weiimport android.util.DisplayMetrics; 26f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 2755ac8ea9519e981bfdbd83c82615c72cfa78d84cShri Bordeimport com.android.ex.photo.PhotoViewController; 28ca8fdcd23fcc53e0429abf8d4ef80e8d6d8fe6faMartin Hibdonimport com.android.ex.photo.loaders.PhotoBitmapLoaderInterface.BitmapResult; 29f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport com.android.ex.photo.util.ImageUtils; 30f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 31f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein/** 32f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Loader for the bitmap of a photo. 33f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein */ 34ca8fdcd23fcc53e0429abf8d4ef80e8d6d8fe6faMartin Hibdonpublic class PhotoBitmapLoader extends AsyncTaskLoader<BitmapResult> 35ca8fdcd23fcc53e0429abf8d4ef80e8d6d8fe6faMartin Hibdon implements PhotoBitmapLoaderInterface { 360c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein private String mPhotoUri; 37f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein private Bitmap mBitmap; 38f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 39f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein public PhotoBitmapLoader(Context context, String photoUri) { 40f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein super(context); 41f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mPhotoUri = photoUri; 42f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 43f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 44ca8fdcd23fcc53e0429abf8d4ef80e8d6d8fe6faMartin Hibdon @Override 450c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein public void setPhotoUri(String photoUri) { 460c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein mPhotoUri = photoUri; 470c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein } 480c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein 49f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 5006d8b5e82b9b75588051a492152fda0b63f70484Mark Wei public BitmapResult loadInBackground() { 5106d8b5e82b9b75588051a492152fda0b63f70484Mark Wei BitmapResult result = new BitmapResult(); 52f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein Context context = getContext(); 53f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (context != null && mPhotoUri != null) { 54f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein final ContentResolver resolver = context.getContentResolver(); 5506d8b5e82b9b75588051a492152fda0b63f70484Mark Wei try { 56112958e7a0493f2e692bbc40d113e98715caaab8Adam Copp result = ImageUtils.createLocalBitmap(resolver, Uri.parse(mPhotoUri), 5755ac8ea9519e981bfdbd83c82615c72cfa78d84cShri Borde PhotoViewController.sMaxPhotoSize); 58112958e7a0493f2e692bbc40d113e98715caaab8Adam Copp if (result.bitmap != null) { 59112958e7a0493f2e692bbc40d113e98715caaab8Adam Copp result.bitmap.setDensity(DisplayMetrics.DENSITY_MEDIUM); 6006d8b5e82b9b75588051a492152fda0b63f70484Mark Wei } 6106d8b5e82b9b75588051a492152fda0b63f70484Mark Wei } catch (UnsupportedOperationException ex) { 6206d8b5e82b9b75588051a492152fda0b63f70484Mark Wei // We got image bytes, but unable to decode to a Bitmap 6306d8b5e82b9b75588051a492152fda0b63f70484Mark Wei result.status = BitmapResult.STATUS_EXCEPTION; 640f7d1502f4f7c0b364e7644875a04fb0c90807ffMark Wei } 65f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 66f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 6706d8b5e82b9b75588051a492152fda0b63f70484Mark Wei return result; 68f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 69f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 70f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** 71f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Called when there is new data to deliver to the client. The 72f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * super class will take care of delivering it; the implementation 73f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * here just adds a little more logic. 74f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein */ 75f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 7606d8b5e82b9b75588051a492152fda0b63f70484Mark Wei public void deliverResult(BitmapResult result) { 7706d8b5e82b9b75588051a492152fda0b63f70484Mark Wei Bitmap bitmap = result != null ? result.bitmap : null; 78f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (isReset()) { 79f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // An async query came in while the loader is stopped. We 80f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // don't need the result. 81f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (bitmap != null) { 82f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein onReleaseResources(bitmap); 83f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 84a3c441f144e3acc7aa32d8236f590cf1aac179f5Andrew Sapperstein return; 85f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 86f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein Bitmap oldBitmap = mBitmap; 87f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mBitmap = bitmap; 88f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 89f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (isStarted()) { 90f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // If the Loader is currently started, we can immediately 91f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // deliver its results. 9206d8b5e82b9b75588051a492152fda0b63f70484Mark Wei super.deliverResult(result); 93f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 94f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 95f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // At this point we can release the resources associated with 96f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // 'oldBitmap' if needed; now that the new result is delivered we 97f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // know that it is no longer in use. 98f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (oldBitmap != null && oldBitmap != bitmap && !oldBitmap.isRecycled()) { 99f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein onReleaseResources(oldBitmap); 100f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 101f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 102f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 103f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** 104f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Handles a request to start the Loader. 105f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein */ 106f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 107f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein protected void onStartLoading() { 108f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (mBitmap != null) { 109f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // If we currently have a result available, deliver it 110f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // immediately. 11106d8b5e82b9b75588051a492152fda0b63f70484Mark Wei BitmapResult result = new BitmapResult(); 11206d8b5e82b9b75588051a492152fda0b63f70484Mark Wei result.status = BitmapResult.STATUS_SUCCESS; 11306d8b5e82b9b75588051a492152fda0b63f70484Mark Wei result.bitmap = mBitmap; 11406d8b5e82b9b75588051a492152fda0b63f70484Mark Wei deliverResult(result); 115f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 116f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 117f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (takeContentChanged() || mBitmap == null) { 118f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // If the data has changed since the last time it was loaded 119f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // or is not currently available, start a load. 120f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein forceLoad(); 121f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 122f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 123f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 124f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** 125f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Handles a request to stop the Loader. 126f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein */ 127f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override protected void onStopLoading() { 128f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // Attempt to cancel the current load task if possible. 129f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein cancelLoad(); 130f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 131f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 132f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** 133f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Handles a request to cancel a load. 134f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein */ 135f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 13606d8b5e82b9b75588051a492152fda0b63f70484Mark Wei public void onCanceled(BitmapResult result) { 13706d8b5e82b9b75588051a492152fda0b63f70484Mark Wei super.onCanceled(result); 138f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 139f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // At this point we can release the resources associated with 'bitmap' 140f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // if needed. 14106d8b5e82b9b75588051a492152fda0b63f70484Mark Wei if (result != null) { 14206d8b5e82b9b75588051a492152fda0b63f70484Mark Wei onReleaseResources(result.bitmap); 14306d8b5e82b9b75588051a492152fda0b63f70484Mark Wei } 144f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 145f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 146f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** 147f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Handles a request to completely reset the Loader. 148f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein */ 149f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein @Override 150f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein protected void onReset() { 151f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein super.onReset(); 152f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 153f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // Ensure the loader is stopped 154f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein onStopLoading(); 155f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 156f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // At this point we can release the resources associated with 'bitmap' 157f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein // if needed. 158f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (mBitmap != null) { 159f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein onReleaseResources(mBitmap); 160f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein mBitmap = null; 161f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 162f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 163f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein 164f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein /** 165f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Helper function to take care of releasing resources associated 166f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * with an actively loaded data set. 167f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein */ 168f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein protected void onReleaseResources(Bitmap bitmap) { 169f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein if (bitmap != null && !bitmap.isRecycled()) { 170f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein bitmap.recycle(); 171f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 172f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein } 173f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein} 174