• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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 
17 package com.android.videoeditor;
18 
19 import java.util.ArrayList;
20 import java.util.HashSet;
21 import java.util.List;
22 import java.util.Set;
23 
24 import android.content.Context;
25 import android.graphics.Bitmap;
26 import android.graphics.drawable.BitmapDrawable;
27 import android.os.AsyncTask;
28 import android.view.View;
29 import android.view.ViewGroup;
30 import android.widget.AbsListView;
31 import android.widget.BaseAdapter;
32 import android.widget.ImageView;
33 import android.widget.TextView;
34 
35 /**
36  * Base class for BaseAdapters which load images.
37  */
38 public abstract class BaseAdapterWithImages<K> extends BaseAdapter {
39     protected final Context mContext;
40     private final List<ImageViewHolder<K>> mViewHolders;
41     // For recording keys of images that are being loaded
42     private final Set<K> mLoadingImages;
43     private final AbsListView mListView;
44 
45     /**
46      * View holder class
47      */
48     protected static class ImageViewHolder<K> {
49         private final ImageView mImageView;
50         private K mKey;
51 
ImageViewHolder(View rowView)52         public ImageViewHolder(View rowView) {
53             mImageView = (ImageView) rowView.findViewById(R.id.item_preview);
54         }
55 
setKey(K key)56         public void setKey(K key) {
57             mKey = key;
58         }
59     }
60 
61     /**
62      * View holder class
63      */
64     protected static class ImageTextViewHolder<K> extends ImageViewHolder<K> {
65         protected final TextView mNameView;
66 
ImageTextViewHolder(View rowView)67         public ImageTextViewHolder(View rowView) {
68             super(rowView);
69             mNameView = (TextView) rowView.findViewById(R.id.item_name);
70         }
71     }
72 
73     /**
74      * Image loader class
75      */
76     protected class ImageLoaderAsyncTask extends AsyncTask<Void, Void, Bitmap> {
77         private final K mKey;
78         private final Object mData;
79 
80         /**
81          * Constructor
82          *
83          * @param key The bitmap key
84          * @param data The data
85          */
ImageLoaderAsyncTask(K key, Object data)86         public ImageLoaderAsyncTask(K key, Object data) {
87             mKey = key;
88             mData = data;
89         }
90 
91         @Override
doInBackground(Void... zzz)92         protected Bitmap doInBackground(Void... zzz) {
93             return loadImage(mData);
94         }
95 
96         @Override
onPostExecute(Bitmap bitmap)97         protected void onPostExecute(Bitmap bitmap) {
98             mLoadingImages.remove(mKey);
99             if (bitmap == null) {
100                 return;
101             }
102 
103             for (ImageViewHolder<K> viewHolder : mViewHolders) {
104                 if (mKey.equals(viewHolder.mKey)) {
105                     viewHolder.mImageView.setImageBitmap(bitmap);
106                     return;
107                 }
108             }
109 
110             bitmap.recycle();
111         }
112     }
113 
114     /**
115      * Constructor
116      *
117      * @param context The context
118      * @param listView The list view
119      */
BaseAdapterWithImages(Context context, AbsListView listView)120     public BaseAdapterWithImages(Context context, AbsListView listView) {
121         mContext = context;
122         mListView = listView;
123         mLoadingImages = new HashSet<K>();
124         mViewHolders = new ArrayList<ImageViewHolder<K>>();
125 
126         mListView.setRecyclerListener(new AbsListView.RecyclerListener() {
127             @Override
128             @SuppressWarnings("unchecked")
129             public void onMovedToScrapHeap(View view) {
130                 final ImageViewHolder<K> viewHolder = (ImageViewHolder<K>)view.getTag();
131 
132                 mViewHolders.remove(viewHolder);
133                 viewHolder.setKey(null);
134 
135                 final BitmapDrawable drawable
136                         = (BitmapDrawable)viewHolder.mImageView.getDrawable();
137                 if (drawable != null && drawable.getBitmap() != null) {
138                     viewHolder.mImageView.setImageDrawable(null);
139                     drawable.getBitmap().recycle();
140                 }
141             }
142         });
143     }
144 
onPause()145     public void onPause() {
146         mViewHolders.clear();
147     }
148 
149     /**
150      * Upon destroy, recycle all images and then remove all child views in the list view.
151      */
onDestroy()152     public void onDestroy() {
153         final int count = mListView.getChildCount();
154         for (int i = 0; i < count; i++) {
155             final View rowView = mListView.getChildAt(i);
156             final ImageView imageView = (ImageView)rowView.findViewById(R.id.item_preview);
157             final BitmapDrawable drawable = (BitmapDrawable)imageView.getDrawable();
158             if (drawable != null && drawable.getBitmap() != null) {
159                 drawable.getBitmap().recycle();
160             }
161         }
162 
163         mListView.removeViews(0, count);
164         System.gc();
165     }
166 
167     /**
168      * Starts the AsyncTask which loads the bitmap.
169      *
170      * @param key The bitmap key
171      * @param data The data
172      * @param viewHolder The view holder
173      */
initiateLoad(K key, Object data, ImageViewHolder<K> viewHolder)174     protected void initiateLoad(K key, Object data, ImageViewHolder<K> viewHolder) {
175         // The adapter may recycle a view and then reuse it.
176         if (!mViewHolders.contains(viewHolder)) {
177             mViewHolders.add(viewHolder);
178         }
179         viewHolder.setKey(key);
180 
181         if (!mLoadingImages.contains(key)) {
182             mLoadingImages.add(key);
183             new ImageLoaderAsyncTask(key, data).execute();
184         }
185     }
186 
187     @Override
getItemId(int position)188     public long getItemId(int position) {
189         return position;
190     }
191 
192     @Override
getCount()193     public abstract int getCount();
194 
195     @Override
getItem(int position)196     public abstract Object getItem(int position);
197 
198     @Override
getView(int position, View convertView, ViewGroup parent)199     public abstract View getView(int position, View convertView, ViewGroup parent);
200 
201     /**
202      * Loads an image based on its key.
203      *
204      * @param data The data required to load the image
205      *
206      * @return The loaded bitmap
207      */
loadImage(Object data)208     protected abstract Bitmap loadImage(Object data);
209 }
210