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.fragments.PhotoViewFragment;
     28 import com.android.ex.photo.loaders.PhotoBitmapLoader.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     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