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