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.AsyncTaskLoader;
21import android.content.ContentResolver;
22import android.content.Context;
23import android.graphics.Bitmap;
24import android.net.Uri;
25import android.util.DisplayMetrics;
26
27import com.android.ex.photo.fragments.PhotoViewFragment;
28import com.android.ex.photo.util.ImageUtils;
29
30/**
31 * Loader for the bitmap of a photo.
32 */
33public class PhotoBitmapLoader extends AsyncTaskLoader<Bitmap> {
34    private String mPhotoUri;
35
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 Bitmap loadInBackground() {
49        Context context = getContext();
50
51        if (context != null && mPhotoUri != null) {
52            final ContentResolver resolver = context.getContentResolver();
53            Bitmap bitmap = ImageUtils.createLocalBitmap(resolver, Uri.parse(mPhotoUri),
54                    PhotoViewFragment.sPhotoSize);
55            if (bitmap != null) {
56                bitmap.setDensity(DisplayMetrics.DENSITY_MEDIUM);
57            }
58            return bitmap;
59        }
60
61        return null;
62    }
63
64    /**
65     * Called when there is new data to deliver to the client.  The
66     * super class will take care of delivering it; the implementation
67     * here just adds a little more logic.
68     */
69    @Override
70    public void deliverResult(Bitmap bitmap) {
71        if (isReset()) {
72            // An async query came in while the loader is stopped.  We
73            // don't need the result.
74            if (bitmap != null) {
75                onReleaseResources(bitmap);
76            }
77        }
78        Bitmap oldBitmap = mBitmap;
79        mBitmap = bitmap;
80
81        if (isStarted()) {
82            // If the Loader is currently started, we can immediately
83            // deliver its results.
84            super.deliverResult(bitmap);
85        }
86
87        // At this point we can release the resources associated with
88        // 'oldBitmap' if needed; now that the new result is delivered we
89        // know that it is no longer in use.
90        if (oldBitmap != null && oldBitmap != bitmap && !oldBitmap.isRecycled()) {
91            onReleaseResources(oldBitmap);
92        }
93    }
94
95    /**
96     * Handles a request to start the Loader.
97     */
98    @Override
99    protected void onStartLoading() {
100        if (mBitmap != null) {
101            // If we currently have a result available, deliver it
102            // immediately.
103            deliverResult(mBitmap);
104        }
105
106        if (takeContentChanged() || mBitmap == null) {
107            // If the data has changed since the last time it was loaded
108            // or is not currently available, start a load.
109            forceLoad();
110        }
111    }
112
113    /**
114     * Handles a request to stop the Loader.
115     */
116    @Override protected void onStopLoading() {
117        // Attempt to cancel the current load task if possible.
118        cancelLoad();
119    }
120
121    /**
122     * Handles a request to cancel a load.
123     */
124    @Override
125    public void onCanceled(Bitmap bitmap) {
126        super.onCanceled(bitmap);
127
128        // At this point we can release the resources associated with 'bitmap'
129        // if needed.
130        onReleaseResources(bitmap);
131    }
132
133    /**
134     * Handles a request to completely reset the Loader.
135     */
136    @Override
137    protected void onReset() {
138        super.onReset();
139
140        // Ensure the loader is stopped
141        onStopLoading();
142
143        // At this point we can release the resources associated with 'bitmap'
144        // if needed.
145        if (mBitmap != null) {
146            onReleaseResources(mBitmap);
147            mBitmap = null;
148        }
149    }
150
151    /**
152     * Helper function to take care of releasing resources associated
153     * with an actively loaded data set.
154     */
155    protected void onReleaseResources(Bitmap bitmap) {
156        if (bitmap != null && !bitmap.isRecycled()) {
157            bitmap.recycle();
158        }
159    }
160}
161