Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android gridview images caching, on scroll images are repeated before replaced

I have GridView with imageviews that are loaded form image thumbnails of the gallery. Am loading these thumbnails from a class where i call a method with the image id and imageview, the method will sets the bitmap to passed imageview.Till here it works perfect but made the thread to pause when we fling the grid view.

My issue here is it pauses when scrolled but the images are repeated in the gridview when scrolled from top to bottom. Am not able to figure out the exact problem. help me out. Thanks!

Here how am setting the pause:

imagegrid.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView absListView, int scrollState) {
                // Pause fetcher to ensure smoother scrolling when flinging
                if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
                    bitmapFromId.setPauseWork(true);
                } else {
                    bitmapFromId.setPauseWork(false);
                }
            }

            @Override
            public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
            }
        });

Here is my get view in grdiview adapter:

public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            if (convertView == null) {
                holder = new ViewHolder();
                convertView = mInflater.inflate(R.layout.galleryitem, null);
                holder.imageview = (ImageView) convertView.findViewById(R.id.thumbImage);
                holder.checkbox = (CheckBox) convertView.findViewById(R.id.itemCheckBox);

                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }
            ImageItem item = images.get(position);
            holder.checkbox.setId(position);
            holder.imageview.setId(position);
            holder.checkbox.setOnClickListener(new OnClickListener() {

                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    CheckBox cb = (CheckBox) v;
                    int id = cb.getId();
                    if (images.get(id).selection) {
                        cb.setChecked(false);
                        images.get(id).selection = false;
                    } else {
                        cb.setChecked(true);
                        images.get(id).selection = true;
                    }
                }
            });
            holder.imageview.setOnClickListener(new OnClickListener() {

                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    int id = v.getId();
                    ImageItem item = images.get(id);
                    Intent intent = new Intent();
                    intent.setAction(Intent.ACTION_VIEW);
                    final String[] columns = { MediaStore.Images.Media.DATA };
                    Cursor imagecursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                            columns, MediaStore.Images.Media._ID + " = " + item.id, null, MediaStore.Images.Media._ID);
                    if (imagecursor != null && imagecursor.getCount() > 0) {
                        imagecursor.moveToPosition(0);
                        String path = imagecursor.getString(imagecursor
                                .getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
                        File file = new File(path);
                        imagecursor.close();
                        intent.setDataAndType(Uri.fromFile(file), "image/*");
                        startActivityForResult(intent, VIEW_IMAGE);
                    }
                }
            });

            holder.imageview.setLayoutParams(mImageViewLayoutParams);

            // Check the height matches our calculated column width
            if (holder.imageview.getLayoutParams().height != mItemHeight) {
                holder.imageview.setLayoutParams(mImageViewLayoutParams);
            }

            bitmapFromId.DisplayImage(item.id, holder.imageview);
            // holder.imageview.setImageBitmap(item.img);
            holder.checkbox.setChecked(item.selection);
            return convertView;
        }

My bitmap loader class:

public class BitmapFromId {

    MemoryCache memoryCache = new MemoryCache();
    FileCache fileCache;
    private Map<ImageView, String> imageViews = Collections.synchronizedMap(new WeakHashMap<ImageView, String>());
    ExecutorService executorService;
    Context context;
    Handler handler = new Handler();// handler to display images in UI thread

    Resources mResources;
    private static final int FADE_IN_TIME = 400;

    private final Object mPauseLock = new Object();

    private boolean mPaused = false;

    public BitmapFromId(Context context) {
        fileCache = new FileCache(context);
        executorService = Executors.newFixedThreadPool(5);
        this.context = context;
        mResources = context.getResources();
    }

    public void DisplayImage(long id, ImageView imageView) {

        Bitmap bitmap = null;
        String _id = String.valueOf(id);
        imageViews.put(imageView, _id);
        bitmap = memoryCache.get(_id);
        if (bitmap != null)
            imageView.setImageBitmap(bitmap);
        else {
            queuePhoto(_id, imageView);
            imageView.setBackgroundResource(R.drawable.empty_photo);
        }
    }

    private void queuePhoto(String id, ImageView imageView) {
        PhotoToLoad p = new PhotoToLoad(id, imageView);
        executorService.submit(new PhotosLoader(p));
    }

    // decodes image
    private Bitmap getImageFromId(String id) {
        Bitmap bitmap;

        long _id = Long.parseLong(id);
        final String[] columns = { MediaStore.Images.Media.DATA };
        final String orderBy = MediaStore.Images.Media._ID;
        Cursor imagecursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns,
                MediaStore.Images.Media._ID + " = " + _id + "", null, orderBy);
        int count = imagecursor.getCount();
        for (int i = 0; i < count; i++) {
            imagecursor.moveToPosition(i);
            bitmap = MediaStore.Images.Thumbnails.getThumbnail(context.getContentResolver(), _id,
                    MediaStore.Images.Thumbnails.MICRO_KIND, null);
            return bitmap;
        }
        imagecursor.close();
        return null;

    }

    // Task for the queue
    private class PhotoToLoad {
        public String id;
        public ImageView imageView;

        public PhotoToLoad(String _i, ImageView i) {
            id = _i;
            imageView = i;
        }
    }

    class PhotosLoader implements Runnable {
        PhotoToLoad photoToLoad;

        PhotosLoader(PhotoToLoad photoToLoad) {
            this.photoToLoad = photoToLoad;
        }

        @Override
        public void run() {
            try {
                if (imageViewReused(photoToLoad))
                    return;
                Bitmap bmp = getImageFromId(photoToLoad.id);
                memoryCache.put(photoToLoad.id, bmp);
                if (imageViewReused(photoToLoad))
                    return;
                BitmapDisplayer bd = new BitmapDisplayer(bmp, photoToLoad);
                handler.post(bd);

                synchronized (mPauseLock) {
                    while (mPaused) {
                        try {
                            mPauseLock.wait();
                        } catch (InterruptedException e) {
                        }
                    }
                }

            } catch (Throwable th) {
                th.printStackTrace();
            }
        }
    }

    boolean imageViewReused(PhotoToLoad photoToLoad) {
        String tag = imageViews.get(photoToLoad.imageView);
        if (tag == null || !tag.equals(photoToLoad.id))
            return true;
        return false;
    }

    // Used to display bitmap in the UI thread
    class BitmapDisplayer implements Runnable {
        Bitmap bitmap;
        PhotoToLoad photoToLoad;

        public BitmapDisplayer(Bitmap b, PhotoToLoad p) {
            bitmap = b;
            photoToLoad = p;

        }

        public void run() {
            if (imageViewReused(photoToLoad))
                return;
            if (bitmap != null) {

                // Load the image fetched:
                final TransitionDrawable td = new TransitionDrawable(new Drawable[] {
                        new ColorDrawable(android.R.color.transparent), new BitmapDrawable(mResources, bitmap) });

                photoToLoad.imageView.setImageDrawable(td);
                td.startTransition(FADE_IN_TIME);

            } else
                photoToLoad.imageView.setImageDrawable(null);
        }
    }

    public void clearCache() {
        memoryCache.clear();
        fileCache.clear();
    }

    public void setPauseWork(boolean pauseWork) {
        if (pauseWork) {
            synchronized (mPauseLock) {
                mPaused = true;
            }
        } else {
            synchronized (mPauseLock) {
                mPaused = false;
                mPauseLock.notifyAll();

            }
        }
    }

}
like image 531
sukarno Avatar asked Nov 03 '22 05:11

sukarno


1 Answers

You can manage all image loading/caching control mechanisim with Aquery framework.

It's very simple. For example, image loading/caching like this;

aq.id(R.id.YourImageViewID).image("http://www.vikispot.com/z/images/vikispot/android-w.png", memCache, fileCache);

See Aquery docs

like image 124
Mustafa Ferhan Avatar answered Nov 11 '22 10:11

Mustafa Ferhan