| /* |
| * Copyright (C) 2011 Google Inc. |
| * Licensed to The Android Open Source Project. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.ex.photo.loaders; |
| |
| import android.content.ContentResolver; |
| import android.content.Context; |
| import android.graphics.Bitmap; |
| import android.net.Uri; |
| import android.support.v4.content.AsyncTaskLoader; |
| import android.util.DisplayMetrics; |
| |
| import com.android.ex.photo.PhotoViewController; |
| import com.android.ex.photo.loaders.PhotoBitmapLoaderInterface.BitmapResult; |
| import com.android.ex.photo.util.ImageUtils; |
| |
| /** |
| * Loader for the bitmap of a photo. |
| */ |
| public class PhotoBitmapLoader extends AsyncTaskLoader<BitmapResult> |
| implements PhotoBitmapLoaderInterface { |
| private String mPhotoUri; |
| private Bitmap mBitmap; |
| |
| public PhotoBitmapLoader(Context context, String photoUri) { |
| super(context); |
| mPhotoUri = photoUri; |
| } |
| |
| @Override |
| public void setPhotoUri(String photoUri) { |
| mPhotoUri = photoUri; |
| } |
| |
| @Override |
| public BitmapResult loadInBackground() { |
| BitmapResult result = new BitmapResult(); |
| Context context = getContext(); |
| if (context != null && mPhotoUri != null) { |
| final ContentResolver resolver = context.getContentResolver(); |
| try { |
| result = ImageUtils.createLocalBitmap(resolver, Uri.parse(mPhotoUri), |
| PhotoViewController.sMaxPhotoSize); |
| if (result.bitmap != null) { |
| result.bitmap.setDensity(DisplayMetrics.DENSITY_MEDIUM); |
| } |
| } catch (UnsupportedOperationException ex) { |
| // We got image bytes, but unable to decode to a Bitmap |
| result.status = BitmapResult.STATUS_EXCEPTION; |
| } |
| } |
| |
| return result; |
| } |
| |
| /** |
| * Called when there is new data to deliver to the client. The |
| * super class will take care of delivering it; the implementation |
| * here just adds a little more logic. |
| */ |
| @Override |
| public void deliverResult(BitmapResult result) { |
| Bitmap bitmap = result != null ? result.bitmap : null; |
| if (isReset()) { |
| // An async query came in while the loader is stopped. We |
| // don't need the result. |
| if (bitmap != null) { |
| onReleaseResources(bitmap); |
| } |
| return; |
| } |
| Bitmap oldBitmap = mBitmap; |
| mBitmap = bitmap; |
| |
| if (isStarted()) { |
| // If the Loader is currently started, we can immediately |
| // deliver its results. |
| super.deliverResult(result); |
| } |
| |
| // At this point we can release the resources associated with |
| // 'oldBitmap' if needed; now that the new result is delivered we |
| // know that it is no longer in use. |
| if (oldBitmap != null && oldBitmap != bitmap && !oldBitmap.isRecycled()) { |
| onReleaseResources(oldBitmap); |
| } |
| } |
| |
| /** |
| * Handles a request to start the Loader. |
| */ |
| @Override |
| protected void onStartLoading() { |
| if (mBitmap != null) { |
| // If we currently have a result available, deliver it |
| // immediately. |
| BitmapResult result = new BitmapResult(); |
| result.status = BitmapResult.STATUS_SUCCESS; |
| result.bitmap = mBitmap; |
| deliverResult(result); |
| } |
| |
| if (takeContentChanged() || mBitmap == null) { |
| // If the data has changed since the last time it was loaded |
| // or is not currently available, start a load. |
| forceLoad(); |
| } |
| } |
| |
| /** |
| * Handles a request to stop the Loader. |
| */ |
| @Override protected void onStopLoading() { |
| // Attempt to cancel the current load task if possible. |
| cancelLoad(); |
| } |
| |
| /** |
| * Handles a request to cancel a load. |
| */ |
| @Override |
| public void onCanceled(BitmapResult result) { |
| super.onCanceled(result); |
| |
| // At this point we can release the resources associated with 'bitmap' |
| // if needed. |
| if (result != null) { |
| onReleaseResources(result.bitmap); |
| } |
| } |
| |
| /** |
| * Handles a request to completely reset the Loader. |
| */ |
| @Override |
| protected void onReset() { |
| super.onReset(); |
| |
| // Ensure the loader is stopped |
| onStopLoading(); |
| |
| // At this point we can release the resources associated with 'bitmap' |
| // if needed. |
| if (mBitmap != null) { |
| onReleaseResources(mBitmap); |
| mBitmap = null; |
| } |
| } |
| |
| /** |
| * Helper function to take care of releasing resources associated |
| * with an actively loaded data set. |
| */ |
| protected void onReleaseResources(Bitmap bitmap) { |
| if (bitmap != null && !bitmap.isRecycled()) { |
| bitmap.recycle(); |
| } |
| } |
| } |