Home | History | Annotate | Download | only in videoeditor
      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 
     52         public ImageViewHolder(View rowView) {
     53             mImageView = (ImageView) rowView.findViewById(R.id.item_preview);
     54         }
     55 
     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 
     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          */
     86         public ImageLoaderAsyncTask(K key, Object data) {
     87             mKey = key;
     88             mData = data;
     89         }
     90 
     91         @Override
     92         protected Bitmap doInBackground(Void... zzz) {
     93             return loadImage(mData);
     94         }
     95 
     96         @Override
     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      */
    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 
    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      */
    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      */
    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
    188     public long getItemId(int position) {
    189         return position;
    190     }
    191 
    192     @Override
    193     public abstract int getCount();
    194 
    195     @Override
    196     public abstract Object getItem(int position);
    197 
    198     @Override
    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      */
    208     protected abstract Bitmap loadImage(Object data);
    209 }
    210