1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.benchmark.ui;
18
19import android.graphics.Bitmap;
20import android.os.AsyncTask;
21import android.view.LayoutInflater;
22import android.view.View;
23import android.view.ViewGroup;
24import android.widget.BaseAdapter;
25import android.widget.ImageView;
26import android.widget.ListAdapter;
27import android.widget.TextView;
28
29import com.android.benchmark.R;
30
31import java.lang.ref.WeakReference;
32import java.util.HashMap;
33
34public class ImageListViewScrollActivity extends ListViewScrollActivity {
35
36    private static final int LIST_SIZE = 100;
37
38    private static final int[] IMG_RES_ID = new int[]{
39            R.drawable.img1,
40            R.drawable.img2,
41            R.drawable.img3,
42            R.drawable.img4,
43            R.drawable.img1,
44            R.drawable.img2,
45            R.drawable.img3,
46            R.drawable.img4,
47            R.drawable.img1,
48            R.drawable.img2,
49            R.drawable.img3,
50            R.drawable.img4,
51            R.drawable.img1,
52            R.drawable.img2,
53            R.drawable.img3,
54            R.drawable.img4,
55    };
56
57    private static Bitmap[] mBitmapCache = new Bitmap[IMG_RES_ID.length];
58
59    private static final String[] WORDS = Utils.buildStringList(LIST_SIZE);
60
61    private HashMap<View, BitmapWorkerTask> mInFlight = new HashMap<>();
62
63    @Override
64    protected ListAdapter createListAdapter() {
65        return new ImageListAdapter();
66    }
67
68    @Override
69    protected String getName() {
70        return getString(R.string.image_list_view_scroll_name);
71    }
72
73    class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
74        private final WeakReference<ImageView> imageViewReference;
75        private int data = 0;
76        private int cacheIdx = 0;
77        volatile boolean cancelled = false;
78
79        public BitmapWorkerTask(ImageView imageView, int cacheIdx) {
80            // Use a WeakReference to ensure the ImageView can be garbage collected
81            imageViewReference = new WeakReference<>(imageView);
82            this.cacheIdx = cacheIdx;
83        }
84
85        // Decode image in background.
86        @Override
87        protected Bitmap doInBackground(Integer... params) {
88            data = params[0];
89            return Utils.decodeSampledBitmapFromResource(getResources(), data, 100, 100);
90        }
91
92        // Once complete, see if ImageView is still around and set bitmap.
93        @Override
94        protected void onPostExecute(Bitmap bitmap) {
95            if (bitmap != null) {
96                final ImageView imageView = imageViewReference.get();
97                if (imageView != null) {
98                    if (!cancelled) {
99                        imageView.setImageBitmap(bitmap);
100                    }
101                    mBitmapCache[cacheIdx] = bitmap;
102                }
103            }
104        }
105    }
106
107    @Override
108    protected void onPause() {
109        super.onPause();
110        for (int i = 0; i < mBitmapCache.length; i++) {
111            mBitmapCache[i] = null;
112        }
113    }
114
115    class ImageListAdapter extends BaseAdapter {
116
117        @Override
118        public int getCount() {
119            return LIST_SIZE;
120        }
121
122        @Override
123        public Object getItem(int postition) {
124            return null;
125        }
126
127        @Override
128        public long getItemId(int postition) {
129            return postition;
130        }
131
132        @Override
133        public View getView(int position, View convertView, ViewGroup parent) {
134            if (convertView == null) {
135                convertView = LayoutInflater.from(getBaseContext())
136                        .inflate(R.layout.image_scroll_list_item, parent, false);
137            }
138
139            ImageView imageView = (ImageView) convertView.findViewById(R.id.image_scroll_image);
140            BitmapWorkerTask inFlight = mInFlight.get(convertView);
141            if (inFlight != null) {
142                inFlight.cancelled = true;
143                mInFlight.remove(convertView);
144            }
145
146            int cacheIdx = position % IMG_RES_ID.length;
147            Bitmap bitmap = mBitmapCache[(cacheIdx)];
148            if (bitmap == null) {
149                BitmapWorkerTask bitmapWorkerTask = new BitmapWorkerTask(imageView, cacheIdx);
150                bitmapWorkerTask.execute(IMG_RES_ID[(cacheIdx)]);
151                mInFlight.put(convertView, bitmapWorkerTask);
152            }
153
154            imageView.setImageBitmap(bitmap);
155
156            TextView textView = (TextView) convertView.findViewById(R.id.image_scroll_text);
157            textView.setText(WORDS[position]);
158
159            return convertView;
160        }
161    }
162}
163