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