PhotoBitmapLoader.java revision 06d8b5e82b9b75588051a492152fda0b63f70484
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 Bitmap bitmap = ImageUtils.createLocalBitmap(resolver, Uri.parse(mPhotoUri), 55 PhotoViewFragment.sPhotoSize); 56 if (bitmap != null) { 57 bitmap.setDensity(DisplayMetrics.DENSITY_MEDIUM); 58 } 59 result.status = BitmapResult.STATUS_SUCCESS; 60 result.bitmap = bitmap; 61 } catch (UnsupportedOperationException ex) { 62 // We got image bytes, but unable to decode to a Bitmap 63 result.status = BitmapResult.STATUS_EXCEPTION; 64 } 65 } 66 67 return result; 68 } 69 70 /** 71 * Called when there is new data to deliver to the client. The 72 * super class will take care of delivering it; the implementation 73 * here just adds a little more logic. 74 */ 75 @Override 76 public void deliverResult(BitmapResult result) { 77 Bitmap bitmap = result != null ? result.bitmap : null; 78 if (isReset()) { 79 // An async query came in while the loader is stopped. We 80 // don't need the result. 81 if (bitmap != null) { 82 onReleaseResources(bitmap); 83 } 84 } 85 Bitmap oldBitmap = mBitmap; 86 mBitmap = bitmap; 87 88 if (isStarted()) { 89 // If the Loader is currently started, we can immediately 90 // deliver its results. 91 super.deliverResult(result); 92 } 93 94 // At this point we can release the resources associated with 95 // 'oldBitmap' if needed; now that the new result is delivered we 96 // know that it is no longer in use. 97 if (oldBitmap != null && oldBitmap != bitmap && !oldBitmap.isRecycled()) { 98 onReleaseResources(oldBitmap); 99 } 100 } 101 102 /** 103 * Handles a request to start the Loader. 104 */ 105 @Override 106 protected void onStartLoading() { 107 if (mBitmap != null) { 108 // If we currently have a result available, deliver it 109 // immediately. 110 BitmapResult result = new BitmapResult(); 111 result.status = BitmapResult.STATUS_SUCCESS; 112 result.bitmap = mBitmap; 113 deliverResult(result); 114 } 115 116 if (takeContentChanged() || mBitmap == null) { 117 // If the data has changed since the last time it was loaded 118 // or is not currently available, start a load. 119 forceLoad(); 120 } 121 } 122 123 /** 124 * Handles a request to stop the Loader. 125 */ 126 @Override protected void onStopLoading() { 127 // Attempt to cancel the current load task if possible. 128 cancelLoad(); 129 } 130 131 /** 132 * Handles a request to cancel a load. 133 */ 134 @Override 135 public void onCanceled(BitmapResult result) { 136 super.onCanceled(result); 137 138 // At this point we can release the resources associated with 'bitmap' 139 // if needed. 140 if (result != null) { 141 onReleaseResources(result.bitmap); 142 } 143 } 144 145 /** 146 * Handles a request to completely reset the Loader. 147 */ 148 @Override 149 protected void onReset() { 150 super.onReset(); 151 152 // Ensure the loader is stopped 153 onStopLoading(); 154 155 // At this point we can release the resources associated with 'bitmap' 156 // if needed. 157 if (mBitmap != null) { 158 onReleaseResources(mBitmap); 159 mBitmap = null; 160 } 161 } 162 163 /** 164 * Helper function to take care of releasing resources associated 165 * with an actively loaded data set. 166 */ 167 protected void onReleaseResources(Bitmap bitmap) { 168 if (bitmap != null && !bitmap.isRecycled()) { 169 bitmap.recycle(); 170 } 171 } 172 173 public class BitmapResult { 174 public static final int STATUS_SUCCESS = 0; 175 public static final int STATUS_EXCEPTION = 1; 176 177 public Bitmap bitmap; 178 public int status; 179 } 180} 181