PhotoBitmapLoader.java revision 112958e7a0493f2e692bbc40d113e98715caaab8
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        }
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