Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package com.octo.android.robospice.spicelist;
  
  import java.io.File;
  import java.util.Arrays;
  import java.util.HashSet;
  import java.util.List;
 import java.util.Set;
 
 
An adapter that is optimized for SpiceListView instances. It offers to update ImageViews contained in SpiceListItemView instances with images loaded from the network. All you have to do is to Override createRequest(java.lang.Object,int,int,int) to define a bitmapRequest for each object in the list that is associated an image to display. Also please note that in your getView(int,android.view.View,android.view.ViewGroup) method, you must call updateListItemViewAsynchronously(java.lang.Object,com.octo.android.robospice.spicelist.SpiceListItemView) in order for your SpiceListItemView to be updated automagically.

Parameters:
<T> the type of data displayed by the list.
Author(s):
sni
 
 public abstract class BaseSpiceArrayAdapter<T> extends ArrayAdapter<T> {
 
     protected int imageWidth = 0;
     protected int imageHeight = 0;

    
Indicates wether to use the network to update data. This is set by the SpiceListView.
 
     protected boolean isNetworkFetchingAllowed = true;
    
A com.octo.android.robospice.SpiceManager that will be used to fetch binaries. It's lifecycle has to be managed at the context level (usually fragment or activity).
 
     protected SpiceManager spiceManagerBinary;
    
List of event listeners to get notified of network fetching allowed changes.
 
Contains all images that have been added recently to the list. They will be animated when first displayed.
 
     private Set<ObjectfreshDrawableSet = new HashSet<Object>();
    
The default drawable to display during image loading from the network.
 
     protected Drawable defaultDrawable;
 
     // ----------------------------
     // --- CONSTRUCTOR
     // ----------------------------
 
     public BaseSpiceArrayAdapter(final Context contextfinal SpiceManager spiceManagerBinary) {
         this(contextspiceManagerBinarynew ArrayList<T>());
     }
 
     public BaseSpiceArrayAdapter(final Context contextfinal SpiceManager spiceManagerBinaryfinal T[] objects) {
         this(contextspiceManagerBinary, Arrays.asList(objects));
     }

    
Used for testing only.
 
     protected BaseSpiceArrayAdapter(final Context contextfinal SpiceManager spiceManagerBinaryfinal List<T> objects) {
         super(context, 0, objects);
         initialize(contextspiceManagerBinary);
     }
 
     // ----------------------------
     // --- PUBLIC API
     // ----------------------------
 
     public final void setDefaultUserDrawable(final Drawable defaultUserDrawable) {
         this. = defaultUserDrawable;
    }
    /* package-private */final void setNetworkFetchingAllowed(final boolean isNetworkFetchingAllowed) {
        boolean changed = isNetworkFetchingAllowed != this.;
        this. = isNetworkFetchingAllowed;
        if (isNetworkFetchingAllowed && changed) {
            fireOnNetworkFetchingAllowedChange();
            Ln.d("calling state change listeners");
        }
    }

    
Updates a SpiceListItemView containing some data. The method createRequest(java.lang.Object,int,int,int) will be applied to data to know which bitmapRequest to execute to get data from network if needed. This method must be called during getView(int,android.view.View,android.view.ViewGroup).

Parameters:
data the data to update the SpiceListItemView with.
spiceListItemView the SpiceListItemView that displays an image to represent data.
    protected final void updateListItemViewAsynchronously(final T datafinal SpiceListItemView<T> spiceListItemView) {
        if (!registered(spiceListItemView)) {
            addSpiceListItemView(spiceListItemView);
        }
        for (int imageIndex = 0; imageIndex < spiceListItemView.getImageViewCount(); imageIndex++) {
             = Math.max(spiceListItemView.getImageView(imageIndex).getWidth());
             = Math.max(spiceListItemView.getImageView(imageIndex).getHeight());
            performBitmapRequestAsync(spiceListItemViewdataimageIndex);
        }
    }
    @SuppressWarnings("unchecked")
    @Override
    public final View getView(final int positionfinal View convertViewfinal ViewGroup parent) {
        SpiceListItemView<T> spiceListItemView;
        T currentItem = getItem(position);
        if (convertView != null) {
            spiceListItemView = (SpiceListItemView<T>) convertView;
        } else {
            spiceListItemView = createView(getContext(), parent);
        }
        spiceListItemView.update(currentItem);
        // this is the most important line. It will update views automatically
        // ----------------------------------------
        updateListItemViewAsynchronously(currentItemspiceListItemView);
        // ----------------------------------------
        return (ViewspiceListItemView;
    }
    public final void performBitmapRequestAsync(final SpiceListItemView<T> spiceListItemViewfinal T datafinal int imageIndex) {
        new ThumbnailAsynTask(createRequest(dataimageIndex)).execute(dataspiceListItemViewimageIndex);
    }
    public abstract SpiceListItemView<T> createView(Context contextViewGroup parent);
    public abstract IBitmapRequest createRequest(T dataint imageIndexint requestImageWidthint requestImageHeight);
    // ----------------------------
    // --- PRIVATE API
    // ----------------------------
    private void addSpiceListItemView(final SpiceListItemView<T> spiceListItemView) {
    }
    private boolean registered(final SpiceListItemView<T> view) {
            if (listener.getView() == view) {
                return true;
            }
        }
        return false;
    }
    private void fireOnNetworkFetchingAllowedChange() {
            for (NetworkFetchingAuthorizationStateChangeAdapter networkFetchingAuthorizationStateChangeListener : ) {
                Ln.d("calling state change listener");
                networkFetchingAuthorizationStateChangeListener.onNetworkFetchingAllowedChange();
            }
        }
    }
    private void initialize(final Context contextfinal SpiceManager spiceManagerBinary) {
        this. = spiceManagerBinary;
    }
    // ----------------------------
    // --- INNER CLASSES
    // ----------------------------
    protected class ImageRequestListener implements RequestListener<Bitmap> {
        private SpiceListItemView<T> spiceListItemView;
        private T data;
        private ImageView thumbImageView;
        private String imageFileName;
        public ImageRequestListener(final T datafinal SpiceListItemView<T> spiceListItemViewfinal int imageIndexfinal String imageFileName) {
            this. = data;
            this. = spiceListItemView;
            this. = spiceListItemView.getImageView(imageIndex);
            this. = imageFileName;
        }
        @Override
        public final void onRequestFailure(final SpiceException spiceException) {
            Ln.e(SpiceListItemView.class.getName(), "Unable to retrive image"spiceException);
        }
        @Override
        public final void onRequestSuccess(final Bitmap bitmap) {
            .add();
            if (this..equals(.getData())) {
                loadBitmapAsynchronously();
            }
        }
    }
    protected void loadBitmapAsynchronously(final T octofinal ImageView thumbImageViewfinal String tempThumbnailImageFileName) {
        if (thumbImageView.getTag() != null && thumbImageView.getTag().equals(tempThumbnailImageFileName)) {
            return;
        }
        if (cancelPotentialWork(tempThumbnailImageFileNamethumbImageView)) {
            final BitmapWorkerTask task = new BitmapWorkerTask(thumbImageViewocto);
            task.fileName = tempThumbnailImageFileName;
            final AsyncDrawable asyncDrawable = new AsyncDrawable(getContext().getResources(), task);
            thumbImageView.setImageDrawable(asyncDrawable);
            thumbImageView.setTag(tempThumbnailImageFileName);
            task.execute(tempThumbnailImageFileName);
        }
    }
    private boolean cancelPotentialWork(final String fileNamefinal ImageView imageView) {
        final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
        if (bitmapWorkerTask != null) {
            final String bitmapFileName = bitmapWorkerTask.fileName;
            if (bitmapFileName == null || !bitmapFileName.equals(fileName)) {
                // Cancel previous task
                bitmapWorkerTask.cancel(true);
            } else {
                // The same work is already in progress
                return false;
            }
        }
        // No task associated with the ImageView, or an existing task was
        // cancelled
        return true;
    }
    protected final BitmapWorkerTask getBitmapWorkerTask(final ImageView imageView) {
        if (imageView != null) {
            final Drawable drawable = imageView.getDrawable();
            if (drawable instanceof BaseSpiceArrayAdapter.AsyncDrawable) {
                @SuppressWarnings("unchecked")
                final AsyncDrawable asyncDrawable = (AsyncDrawabledrawable;
                return asyncDrawable.getBitmapWorkerTask();
            }
        }
        return null;
    }
    // ----------------------------------
    // INNER CLASSES
    // ----------------------------------
    protected class ThumbnailAsynTask extends AsyncTask<ObjectVoidBoolean> {
        private T data;
        private SpiceListItemView<T> spiceListItemView;
        private String tempThumbnailImageFileName = "";
        private IBitmapRequest bitmapRequest;
        private int imageIndex;
        public ThumbnailAsynTask(final IBitmapRequest request) {
            this. = request;
        }
        @SuppressWarnings("unchecked")
        @Override
        protected final Boolean doInBackground(final Object... params) {
             = (T) params[0];
             = (SpiceListItemView<T>) params[1];
             = (Integerparams[2];
            if ( != null) {
                File tempThumbnailImageFile = .getCacheFile();
                 = tempThumbnailImageFile.getAbsolutePath();
                Ln.d("Filename : " + );
                if (!tempThumbnailImageFile.exists()) {
                    if () {
                        ImageRequestListener imageRequestListener = new ImageRequestListener();
                        .execute((SpiceRequest<Bitmap>) "THUMB_IMAGE_" + .hashCode(), .imageRequestListener);
                    }
                    return false;
                }
            }
            return true;
        }
        @Override
        protected final void onPostExecute(final Boolean isImageAvailableInCache) {
            if (isImageAvailableInCache) {
            } else {
            }
        }
    }
    private class BitmapWorkerTask extends AsyncTask<StringVoidDrawable> {
        private final WeakReference<ImageViewimageViewReference;
        String fileName = "";
        private T data;
        private Animation animation;
        public BitmapWorkerTask(final ImageView imageViewfinal T data) {
            // Use a WeakReference to ensure the ImageView can be garbage
            // collected
             = new WeakReference<ImageView>(imageView);
            this. = data;
        }
        // Decode image in background.
        @Override
        protected Drawable doInBackground(final String... params) {
             = AnimationUtils.loadAnimation(getContext(), ...);
             = params[0];
            return new BitmapDrawable(getContext().getResources(), BitmapFactory.decodeFile(null));
        }
        // Once complete, see if ImageView is still around and set bitmap.
        @Override
        protected void onPostExecute(Drawable drawable) {
            if (isCancelled()) {
                drawable = null;
            }
            if ( != null && drawable != null) {
                final ImageView imageView = .get();
                final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
                if (this == bitmapWorkerTask) {
                    if (.remove()) {
                        .setAnimationListener(new TransientStateAnimationListener(imageView));
                        imageView.startAnimation();
                    }
                    imageView.setImageDrawable(drawable);
                }
            }
        }
    }
        public NetworkFetchingAuthorizationStateChangeAdapter(final SpiceListItemView<T> spiceListItemView) {
            this. = new WeakReference<SpiceListItemView<T>>(spiceListItemView);
        }
        public void onNetworkFetchingAllowedChange(final boolean networkFetchingAllowed) {
            SpiceListItemView<T> spiceListItemView = .get();
            if (spiceListItemView != null) {
                T data = spiceListItemView.getData();
                for (int imageIndex = 0; imageIndex < spiceListItemView.getImageViewCount(); imageIndex++) {
                    performBitmapRequestAsync(spiceListItemViewdataimageIndex);
                }
            }
        }
        public SpiceListItemView<T> getView() {
            return .get();
        }
    }
    private class AsyncDrawable extends BitmapDrawable {
        public AsyncDrawable(final Resources resfinal BitmapWorkerTask bitmapWorkerTask) {
            super(res);
             = new WeakReference<BitmapWorkerTask>(bitmapWorkerTask);
        }
        public BitmapWorkerTask getBitmapWorkerTask() {
            return .get();
        }
    }
    private final class TransientStateAnimationListener implements AnimationListener {
        private final ImageView imageView;
        private TransientStateAnimationListener(ImageView imageView) {
            this. = imageView;
        }
        @Override
        public void onAnimationStart(final Animation animation) {
            .setHasTransientState(true);
        }
        @Override
        public void onAnimationRepeat(final Animation animation) {
        }
        @Override
        public void onAnimationEnd(final Animation animation) {
            .setHasTransientState(false);
        }
    }
New to GrepCode? Check out our FAQ X