Android gridview图像缓存,在更换之前重复滚动图像

时间:2013-02-06 07:15:57

标签: android performance android-imageview android-gridview android-adapter

我有GridView,其中的图像视图是从图库的图像缩略图加载的。我从一个用图像id和imageview调用方法的类中加载这些缩略图,该方法会将位图设置为通过imageview。这里它工作得很完美,但是当我们抛出网格视图时让线程暂停。

我的问题是它在滚动时暂停,但是当从上到下滚动时,图像在gridview中重复出现。我无法弄清楚确切的问题。帮帮我。谢谢!

这里是如何设置暂停:

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) {
            }
        });

以下是我在grdiview适配器中的获取视图:

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;
        }

我的位图加载器类:

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();

            }
        }
    }

}

1 个答案:

答案 0 :(得分:2)

您可以使用A Query框架管理所有图像加载/缓存控制机制。

这很简单。例如,像这样的图像加载/缓存;

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

请参阅Aquery文档