Home | History | Annotate | Download | only in loaders
      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 
     18 package com.android.ex.photo.loaders;
     19 
     20 import android.content.ContentResolver;
     21 import android.content.Context;
     22 import android.graphics.Bitmap;
     23 import android.net.Uri;
     24 import android.support.v4.content.AsyncTaskLoader;
     25 import android.util.DisplayMetrics;
     26 
     27 import com.android.ex.photo.PhotoViewController;
     28 import com.android.ex.photo.loaders.PhotoBitmapLoaderInterface.BitmapResult;
     29 import com.android.ex.photo.util.ImageUtils;
     30 
     31 /**
     32  * Loader for the bitmap of a photo.
     33  */
     34 public class PhotoBitmapLoader extends AsyncTaskLoader<BitmapResult>
     35     implements PhotoBitmapLoaderInterface {
     36     private String mPhotoUri;
     37     private Bitmap mBitmap;
     38 
     39     public PhotoBitmapLoader(Context context, String photoUri) {
     40         super(context);
     41         mPhotoUri = photoUri;
     42     }
     43 
     44     @Override
     45     public void setPhotoUri(String photoUri) {
     46         mPhotoUri = photoUri;
     47     }
     48 
     49     @Override
     50     public BitmapResult loadInBackground() {
     51         BitmapResult result = new BitmapResult();
     52         Context context = getContext();
     53         if (context != null && mPhotoUri != null) {
     54             final ContentResolver resolver = context.getContentResolver();
     55             try {
     56                 result = ImageUtils.createLocalBitmap(resolver, Uri.parse(mPhotoUri),
     57                         PhotoViewController.sMaxPhotoSize);
     58                 if (result.bitmap != null) {
     59                     result.bitmap.setDensity(DisplayMetrics.DENSITY_MEDIUM);
     60                 }
     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             return;
     85         }
     86         Bitmap oldBitmap = mBitmap;
     87         mBitmap = bitmap;
     88 
     89         if (isStarted()) {
     90             // If the Loader is currently started, we can immediately
     91             // deliver its results.
     92             super.deliverResult(result);
     93         }
     94 
     95         // At this point we can release the resources associated with
     96         // 'oldBitmap' if needed; now that the new result is delivered we
     97         // know that it is no longer in use.
     98         if (oldBitmap != null && oldBitmap != bitmap && !oldBitmap.isRecycled()) {
     99             onReleaseResources(oldBitmap);
    100         }
    101     }
    102 
    103     /**
    104      * Handles a request to start the Loader.
    105      */
    106     @Override
    107     protected void onStartLoading() {
    108         if (mBitmap != null) {
    109             // If we currently have a result available, deliver it
    110             // immediately.
    111             BitmapResult result = new BitmapResult();
    112             result.status = BitmapResult.STATUS_SUCCESS;
    113             result.bitmap = mBitmap;
    114             deliverResult(result);
    115         }
    116 
    117         if (takeContentChanged() || mBitmap == null) {
    118             // If the data has changed since the last time it was loaded
    119             // or is not currently available, start a load.
    120             forceLoad();
    121         }
    122     }
    123 
    124     /**
    125      * Handles a request to stop the Loader.
    126      */
    127     @Override protected void onStopLoading() {
    128         // Attempt to cancel the current load task if possible.
    129         cancelLoad();
    130     }
    131 
    132     /**
    133      * Handles a request to cancel a load.
    134      */
    135     @Override
    136     public void onCanceled(BitmapResult result) {
    137         super.onCanceled(result);
    138 
    139         // At this point we can release the resources associated with 'bitmap'
    140         // if needed.
    141         if (result != null) {
    142             onReleaseResources(result.bitmap);
    143         }
    144     }
    145 
    146     /**
    147      * Handles a request to completely reset the Loader.
    148      */
    149     @Override
    150     protected void onReset() {
    151         super.onReset();
    152 
    153         // Ensure the loader is stopped
    154         onStopLoading();
    155 
    156         // At this point we can release the resources associated with 'bitmap'
    157         // if needed.
    158         if (mBitmap != null) {
    159             onReleaseResources(mBitmap);
    160             mBitmap = null;
    161         }
    162     }
    163 
    164     /**
    165      * Helper function to take care of releasing resources associated
    166      * with an actively loaded data set.
    167      */
    168     protected void onReleaseResources(Bitmap bitmap) {
    169         if (bitmap != null && !bitmap.isRecycled()) {
    170             bitmap.recycle();
    171         }
    172     }
    173 }
    174