Android ListView 使用 AsyncTask 更新图像缩略图导致视图回收 [英] Android ListView updating of Image Thumbnails using AsyncTask Causes View recycling

查看:20
本文介绍了Android ListView 使用 AsyncTask 更新图像缩略图导致视图回收的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试让缩略图与 ListView 中的图像文件的 AsyncTask 一起使用.我一直有行回收的常见问题,因此在滚动缩略图时被分配到错误的行.我曾尝试向 ImageView 添加标签,然后在 AsyncTask 的 onPostExecute() 中确认标签,但是我的尝试没有成功.有人请帮忙!

I have been trying to get thumbnails to work with an AsyncTask for image files in a ListView. I have been having the common problem of Row Recycling, and thus on scrolling thumbnails are being assigned to wrong rows. I have tried adding tags to the ImageView and then confirming the tags in the onPostExecute() in the AsyncTask, but however have been unsuccessful in my attempts. Someone please help!

自定义适配器如下:

public class MySimpleAdapter extends SimpleAdapter {

        public MySimpleAdapter(Context context,
                List<? extends Map<String, ?>> data, int resource,
                String[] from, int[] to) {
            super(context, data, resource, from, to);
            // TODO Auto-generated constructor stub
        }

        public View getView(int position, View convertView, ViewGroup parent) {
            final View v = super.getView(position, convertView, parent);
            thumbnail = (ImageView) v.findViewById(R.id.thumbnail);
            checker = (CheckBox) v.findViewById(R.id.checkBox);
            filenametext = (TextView) v.findViewById(R.id.text1);
            String pathtoimage = startLocation.concat("/"
                    + filenametext.getText().toString());
            desctext = (TextView) v.findViewById(R.id.text2);
            String temp = desctext.getText().toString();
            if (temp.equals("Directory") == true) {
                checker.setEnabled(false);
                switch (theme) {
                case 0:
                    thumbnail.setImageResource(R.drawable.folder_light);
                    break;
                case 1:
                    thumbnail.setImageResource(R.drawable.folder_dark);
                    break;
                }

            } else {
                checker.setEnabled(true);
                if (filenametext.getText().toString().endsWith(".jpg")
                        || filenametext.getText().toString().endsWith(".png")
                        || filenametext.getText().toString().endsWith(".bmp")) {
                    Boolean hashmapfound = false;
                    for (HashMap.Entry<String, Bitmap> entry : thumbnaillist
                            .entrySet()) {
                        String key = entry.getKey();
                        if (key.equals(filenametext.getText().toString())) {
                            Log.d(TAG, "HashMapKey Found!");
                            thumbnail.setImageBitmap(entry.getValue());
                            hashmapfound = true;
                        }
                    }
                    if (!hashmapfound) {
                        Log.d(TAG, "NO HashMapKey Found! Adding to HashMap!");
                        switch (theme) {
                        case 0:
                            thumbnail
                                    .setImageResource(R.drawable.unknown_image_light);
                            break;
                        case 1:
                            thumbnail
                                    .setImageResource(R.drawable.unknown_image_dark);
                            break;
                        }
                        thumbnail.setTag((filenametext.getText().toString()));
                        new GetBitMaps(thumbnail).execute(pathtoimage,
                                filenametext.getText().toString());
                    }

                } else {
                    switch (theme) {
                    case 0:
                        thumbnail.setImageResource(R.drawable.file_light);
                        break;
                    case 1:
                        thumbnail.setImageResource(R.drawable.file_dark);
                        break;
                    }
                }
            }
            return v;
        }

    }

AsyncTask 如下:

The AsyncTask is as follows :

class GetBitMaps extends AsyncTask<String, Void, Bitmap> {

    private ImageView thumbnail;
    private String imageName;

    public GetBitMaps(ImageView thumb) {
        // TODO Auto-generated constructor stub
        thumbnail = thumb;
    }

    @Override
    protected Bitmap doInBackground(String... pathtoimage) {
        Bitmap bmp = createThumbnail(pathtoimage[0]);
        thumbnaillist.put(pathtoimage[1], bmp);
        imageName = pathtoimage[1];
        return bmp;
    }

    @Override
    protected void onPostExecute(Bitmap bmp) {

        if (((String) thumbnail.getTag()).equals(imageName)) {
            thumbnail.setImageBitmap(bmp);
        }
    }

    private Bitmap createThumbnail(String filepath) {
        Bitmap bmp = BitmapFactory.decodeFile(filepath);
        int w = bmp.getWidth();
        int h = bmp.getHeight();
        if (w > h) {
            w = 80;
            h = 40;
        } else if (w < h) {
            w = 40;
            h = 80;
        }
        bmp = Bitmap.createScaledBitmap(bmp, w, h, true);

        return bmp;
    }
}

我仍然不知道还能做什么才能让缩略图在滚动时显示在正确的行上.

I still cannot figure out what else to do in order to get the Thumbnails to display at the correct rows WHILE SCROLLING.

请注意:从受影响的行滚动并向下滚动后,一切正常,但滚动问题并未消失!

Please Note: After scrolling away from the affected rows and scrolling back down, things work fine, but the scrolling problem is not going away!

推荐答案

来自 这篇博文:

您想要做的是在单独的线程中异步运行所有每行 IO 或任何繁重的 CPU 绑定例程.这里的技巧是做到这一点并且仍然遵守 ListView 的回收行为.例如,如果您运行 AsyncTask 以在适配器的 getView() 中加载个人资料图片,则您正在为其加载图像的视图可能会在 AsyncTask 完成之前被回收到另一个位置.因此,您需要一种机制来知道在完成异步操作后视图是否还没有被回收.

What you want to do is running all per-row IO or any heavy CPU-bound routine asynchronously in a separate thread. The trick here is to do that and still comply with ListView‘s recycling behaviour. For instance, if you run an AsyncTask to load a profile picture in the adapter’s getView(), the view you’re loading the image for might be recycled for another position before the AsyncTask finishes. So, you need a mechanism to know if the view hasn’t been recycled once you’re done with the async operation.

实现此目的的一种简单方法是将一些信息附加到视图中,以标识与其关联的行.然后您可以检查异步操作完成时视图的目标行是否仍然相同.有很多方法可以实现这一点.这只是您可以做到的一种方式的简单草图:

One simple way to achieve this is to attach some piece of information to the view that identifies which row is associated with it. Then you can check if the target row for the view is still the same when the async operation finishes. There are many ways of achieving this. Here is just a simplistic sketch of one way you could do it:

public View getView(int position, View convertView,
        ViewGroup parent) {
    ViewHolder holder;

    ...

    holder.position = position;

    new ThumbnailTask(position, holder)
            .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null);

    return convertView;
}

private static class ThumbnailTask extends AsyncTask {
    private int mPosition;
    private ViewHolder mHolder;

    public ThumbnailTask(int position, ViewHolder holder) {
        mPosition = position;
        mHolder = holder;
    }

    @Override
    protected Cursor doInBackground(Void... arg0) {
        // Download bitmap here
    }

    @Override
    protected void onPostExecute(Bitmap bitmap) {
        if (mHolder.position == mPosition) {
            mHolder.thumbnail.setImageBitmap(bitmap);
        }
    }
}

private static class ViewHolder {
    public ImageView thumbnail;
    public int position;
}

这篇关于Android ListView 使用 AsyncTask 更新图像缩略图导致视图回收的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆