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.util.LruCache;
24ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banesimport android.widget.ImageView;
25ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes
26ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes/**
27ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes * A very naive lazily implemented image loader. Do not use this in production code.
28ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes */
29ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banesclass ImageLoader {
30ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes
31ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes    /**
32ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes     * A LruCache used to store images which has a maximum size of 10% of the maximum heap size.
33ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes     */
34ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes    private static final BitmapCache CACHE = new BitmapCache(
35ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            Math.round(Runtime.getRuntime().maxMemory() / 10));
36ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes
37ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes    private ImageLoader() {
38ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes    }
39ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes
40ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes    interface Listener {
41ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes        void onImageLoaded(Bitmap bitmap);
42ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes    }
43ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes
44ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes    static void loadMediaStoreThumbnail(final ImageView imageView,
45ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            final long id,
46ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            final Listener listener) {
47ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes
48ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes        final Bitmap cachedValue = CACHE.get(id);
49ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes        if (cachedValue != null) {
50ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            // If the image is already in the cache, display the image,
51ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            // call the listener now and return
52ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            imageView.setImageBitmap(cachedValue);
53ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            if (listener != null) {
54ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes                listener.onImageLoaded(cachedValue);
55ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            }
56ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            return;
57ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes        }
58ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes
5964165762788d147a6def5d6a89d6cd884b0f49f3Aurimas Liutikas        new AsyncTask<Void, Void, Bitmap>() {
60ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            @Override
61ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            protected Bitmap doInBackground(Void... params) {
62ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes                return MediaStore.Images.Thumbnails.getThumbnail(
63ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes                        imageView.getContext().getContentResolver(),
64ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes                        id,
65ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes                        MediaStore.Images.Thumbnails.MINI_KIND,
66ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes                        null);
67ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            }
68ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes
69ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            @Override
70ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            protected void onPostExecute(Bitmap bitmap) {
71ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes                imageView.setImageBitmap(bitmap);
72ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes
73ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes                if (bitmap != null) {
74ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes                    // Add the image to the memory cache first
75ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes                    CACHE.put(id, bitmap);
76ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes
77ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes                    if (listener != null) {
78ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes                        listener.onImageLoaded(bitmap);
79ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes                    }
80ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes                }
81ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            }
8264165762788d147a6def5d6a89d6cd884b0f49f3Aurimas Liutikas        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
83ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes    }
84ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes
85ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes    /**
86ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes     * A simple cache implementation for {@link android.graphics.Bitmap} instances which uses
87ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes     * {@link android.support.v4.util.LruCache}.
88ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes     */
89ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes    private static class BitmapCache extends LruCache<Long, Bitmap> {
90ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes        BitmapCache(int maxSize) {
91ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            super(maxSize);
92ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes        }
93ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes
94ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes        @Override
95ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes        protected int sizeOf(Long key, Bitmap value) {
96ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes            return BitmapCompat.getAllocationByteCount(value);
97ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes        }
98ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes    }
99ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes
100ef3b66039ff877b61bbc823921f6033d777cd3c8Chris Banes}
101