PhotoBitmapLoader.java revision a3c441f144e3acc7aa32d8236f590cf1aac179f5
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 return; 83 } 84 Bitmap oldBitmap = mBitmap; 85 mBitmap = bitmap; 86 87 if (isStarted()) { 88 // If the Loader is currently started, we can immediately 89 // deliver its results. 90 super.deliverResult(result); 91 } 92 93 // At this point we can release the resources associated with 94 // 'oldBitmap' if needed; now that the new result is delivered we 95 // know that it is no longer in use. 96 if (oldBitmap != null && oldBitmap != bitmap && !oldBitmap.isRecycled()) { 97 onReleaseResources(oldBitmap); 98 } 99 } 100 101 /** 102 * Handles a request to start the Loader. 103 */ 104 @Override 105 protected void onStartLoading() { 106 if (mBitmap != null) { 107 // If we currently have a result available, deliver it 108 // immediately. 109 BitmapResult result = new BitmapResult(); 110 result.status = BitmapResult.STATUS_SUCCESS; 111 result.bitmap = mBitmap; 112 deliverResult(result); 113 } 114 115 if (takeContentChanged() || mBitmap == null) { 116 // If the data has changed since the last time it was loaded 117 // or is not currently available, start a load. 118 forceLoad(); 119 } 120 } 121 122 /** 123 * Handles a request to stop the Loader. 124 */ 125 @Override protected void onStopLoading() { 126 // Attempt to cancel the current load task if possible. 127 cancelLoad(); 128 } 129 130 /** 131 * Handles a request to cancel a load. 132 */ 133 @Override 134 public void onCanceled(BitmapResult result) { 135 super.onCanceled(result); 136 137 // At this point we can release the resources associated with 'bitmap' 138 // if needed. 139 if (result != null) { 140 onReleaseResources(result.bitmap); 141 } 142 } 143 144 /** 145 * Handles a request to completely reset the Loader. 146 */ 147 @Override 148 protected void onReset() { 149 super.onReset(); 150 151 // Ensure the loader is stopped 152 onStopLoading(); 153 154 // At this point we can release the resources associated with 'bitmap' 155 // if needed. 156 if (mBitmap != null) { 157 onReleaseResources(mBitmap); 158 mBitmap = null; 159 } 160 } 161 162 /** 163 * Helper function to take care of releasing resources associated 164 * with an actively loaded data set. 165 */ 166 protected void onReleaseResources(Bitmap bitmap) { 167 if (bitmap != null && !bitmap.isRecycled()) { 168 bitmap.recycle(); 169 } 170 } 171 172 public static class BitmapResult { 173 public static final int STATUS_SUCCESS = 0; 174 public static final int STATUS_EXCEPTION = 1; 175 176 public Bitmap bitmap; 177 public int status; 178 } 179} 180