PhotoBitmapLoader.java revision 112958e7a0493f2e692bbc40d113e98715caaab8
1/* 2 * Copyright (C) 2011 Google Inc. 3 * Licensed to The Android Open Source Project. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package com.android.ex.photo.loaders; 19 20import android.content.ContentResolver; 21import android.content.Context; 22import android.graphics.Bitmap; 23import android.net.Uri; 24import android.support.v4.content.AsyncTaskLoader; 25import android.util.DisplayMetrics; 26 27import com.android.ex.photo.fragments.PhotoViewFragment; 28import com.android.ex.photo.loaders.PhotoBitmapLoader.BitmapResult; 29import com.android.ex.photo.util.ImageUtils; 30 31/** 32 * Loader for the bitmap of a photo. 33 */ 34public class PhotoBitmapLoader extends AsyncTaskLoader<BitmapResult> { 35 private String mPhotoUri; 36 private Bitmap mBitmap; 37 38 public PhotoBitmapLoader(Context context, String photoUri) { 39 super(context); 40 mPhotoUri = photoUri; 41 } 42 43 public void setPhotoUri(String photoUri) { 44 mPhotoUri = photoUri; 45 } 46 47 @Override 48 public BitmapResult loadInBackground() { 49 BitmapResult result = new BitmapResult(); 50 Context context = getContext(); 51 if (context != null && mPhotoUri != null) { 52 final ContentResolver resolver = context.getContentResolver(); 53 try { 54 result = ImageUtils.createLocalBitmap(resolver, Uri.parse(mPhotoUri), 55 PhotoViewFragment.sPhotoSize); 56 if (result.bitmap != null) { 57 result.bitmap.setDensity(DisplayMetrics.DENSITY_MEDIUM); 58 } 59 } catch (UnsupportedOperationException ex) { 60 // We got image bytes, but unable to decode to a Bitmap 61 result.status = BitmapResult.STATUS_EXCEPTION; 62 } 63 } 64 65 return result; 66 } 67 68 /** 69 * Called when there is new data to deliver to the client. The 70 * super class will take care of delivering it; the implementation 71 * here just adds a little more logic. 72 */ 73 @Override 74 public void deliverResult(BitmapResult result) { 75 Bitmap bitmap = result != null ? result.bitmap : null; 76 if (isReset()) { 77 // An async query came in while the loader is stopped. We 78 // don't need the result. 79 if (bitmap != null) { 80 onReleaseResources(bitmap); 81 } 82 } 83 Bitmap oldBitmap = mBitmap; 84 mBitmap = bitmap; 85 86 if (isStarted()) { 87 // If the Loader is currently started, we can immediately 88 // deliver its results. 89 super.deliverResult(result); 90 } 91 92 // At this point we can release the resources associated with 93 // 'oldBitmap' if needed; now that the new result is delivered we 94 // know that it is no longer in use. 95 if (oldBitmap != null && oldBitmap != bitmap && !oldBitmap.isRecycled()) { 96 onReleaseResources(oldBitmap); 97 } 98 } 99 100 /** 101 * Handles a request to start the Loader. 102 */ 103 @Override 104 protected void onStartLoading() { 105 if (mBitmap != null) { 106 // If we currently have a result available, deliver it 107 // immediately. 108 BitmapResult result = new BitmapResult(); 109 result.status = BitmapResult.STATUS_SUCCESS; 110 result.bitmap = mBitmap; 111 deliverResult(result); 112 } 113 114 if (takeContentChanged() || mBitmap == null) { 115 // If the data has changed since the last time it was loaded 116 // or is not currently available, start a load. 117 forceLoad(); 118 } 119 } 120 121 /** 122 * Handles a request to stop the Loader. 123 */ 124 @Override protected void onStopLoading() { 125 // Attempt to cancel the current load task if possible. 126 cancelLoad(); 127 } 128 129 /** 130 * Handles a request to cancel a load. 131 */ 132 @Override 133 public void onCanceled(BitmapResult result) { 134 super.onCanceled(result); 135 136 // At this point we can release the resources associated with 'bitmap' 137 // if needed. 138 if (result != null) { 139 onReleaseResources(result.bitmap); 140 } 141 } 142 143 /** 144 * Handles a request to completely reset the Loader. 145 */ 146 @Override 147 protected void onReset() { 148 super.onReset(); 149 150 // Ensure the loader is stopped 151 onStopLoading(); 152 153 // At this point we can release the resources associated with 'bitmap' 154 // if needed. 155 if (mBitmap != null) { 156 onReleaseResources(mBitmap); 157 mBitmap = null; 158 } 159 } 160 161 /** 162 * Helper function to take care of releasing resources associated 163 * with an actively loaded data set. 164 */ 165 protected void onReleaseResources(Bitmap bitmap) { 166 if (bitmap != null && !bitmap.isRecycled()) { 167 bitmap.recycle(); 168 } 169 } 170 171 public static class BitmapResult { 172 public static final int STATUS_SUCCESS = 0; 173 public static final int STATUS_EXCEPTION = 1; 174 175 public Bitmap bitmap; 176 public int status; 177 } 178} 179