ImageLoader.java revision ef3b66039ff877b61bbc823921f6033d777cd3c8
1ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes/*
2ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes * Copyright (C) 2014 The Android Open Source Project
3ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes *
4ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes * Licensed under the Apache License, Version 2.0 (the "License");
5ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes * you may not use this file except in compliance with the License.
6ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes * You may obtain a copy of the License at
7ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes *
8ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes *      http://www.apache.org/licenses/LICENSE-2.0
9ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes *
10ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes * Unless required by applicable law or agreed to in writing, software
11ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes * distributed under the License is distributed on an "AS IS" BASIS,
12ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes * See the License for the specific language governing permissions and
14ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes * limitations under the License.
15ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes */
16ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes
17ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banespackage com.example.android.supportv7.graphics;
18ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes
19ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banesimport android.graphics.Bitmap;
20ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banesimport android.os.AsyncTask;
21ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banesimport android.provider.MediaStore;
22ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banesimport android.support.v4.graphics.BitmapCompat;
23ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banesimport android.support.v4.os.AsyncTaskCompat;
24ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banesimport android.support.v4.util.LruCache;
25ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banesimport android.widget.ImageView;
26ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes
27ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes/**
28ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes * A very naive lazily implemented image loader. Do not use this in production code.
29ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes */
30ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banesclass ImageLoader {
31ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes
32ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes    /**
33ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes     * A LruCache used to store images which has a maximum size of 10% of the maximum heap size.
34ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes     */
35ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes    private static final BitmapCache CACHE = new BitmapCache(
36ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            Math.round(Runtime.getRuntime().maxMemory() / 10));
37ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes
38ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes    private ImageLoader() {
39ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes    }
40ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes
41ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes    interface Listener {
42ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes        void onImageLoaded(Bitmap bitmap);
43ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes    }
44ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes
45ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes    static void loadMediaStoreThumbnail(final ImageView imageView,
46ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            final long id,
47ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            final Listener listener) {
48ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes
49ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes        final Bitmap cachedValue = CACHE.get(id);
50ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes        if (cachedValue != null) {
51ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            // If the image is already in the cache, display the image,
52ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            // call the listener now and return
53ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            imageView.setImageBitmap(cachedValue);
54ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            if (listener != null) {
55ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes                listener.onImageLoaded(cachedValue);
56ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            }
57ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            return;
58ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes        }
59ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes
60ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes        AsyncTaskCompat.executeParallel(new AsyncTask<Void, Void, Bitmap>() {
61ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            @Override
62ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            protected Bitmap doInBackground(Void... params) {
63ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes                return MediaStore.Images.Thumbnails.getThumbnail(
64ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes                        imageView.getContext().getContentResolver(),
65ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes                        id,
66ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes                        MediaStore.Images.Thumbnails.MINI_KIND,
67ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes                        null);
68ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            }
69ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes
70ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            @Override
71ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            protected void onPostExecute(Bitmap bitmap) {
72ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes                imageView.setImageBitmap(bitmap);
73ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes
74ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes                if (bitmap != null) {
75ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes                    // Add the image to the memory cache first
76ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes                    CACHE.put(id, bitmap);
77ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes
78ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes                    if (listener != null) {
79ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes                        listener.onImageLoaded(bitmap);
80ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes                    }
81ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes                }
82ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            }
83ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes        });
84ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes    }
85ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes
86ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes    /**
87ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes     * A simple cache implementation for {@link android.graphics.Bitmap} instances which uses
88ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes     * {@link android.support.v4.util.LruCache}.
89ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes     */
90ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes    private static class BitmapCache extends LruCache<Long, Bitmap> {
91ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes        BitmapCache(int maxSize) {
92ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            super(maxSize);
93ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes        }
94ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes
95ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes        @Override
96ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes        protected int sizeOf(Long key, Bitmap value) {
97ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            return BitmapCompat.getAllocationByteCount(value);
98ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes        }
99ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes    }
100ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes
101ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes}
102