1

我有带有 EventAdapter 的 ListView。

public class EventAdapter extends BaseAdapter {
...
public View getView(int position, View view, ViewGroup parent) {
     ...
     cache.imgIcon.setImageDrawable(ImgCache.setImg(url, progressBar));
     ...
}

ImgCache 它的类用于缓存图像。

public class ImgCache {
    public static HashMap<String, Drawable> imgCache;

    // get img from cache if exist, or download and put in cache
    public static Drawable setImg(final String link, final ProgressBar progressBar) {
        final Drawable[] image = {null};
        if (imgCache.containsKey(link)) {
            image[0] = imgCache.get(link);
            progressBar.setVisibility(View.INVISIBLE);
        } else {
            new AsyncTask<Void, Void, Drawable>() {
                @Override
                protected Drawable doInBackground(Void... params) {
                    URL url = null;
                    try {
                        url = new URL(link);
                        URLConnection connection = url.openConnection();
                        image[0] = Drawable.createFromStream(connection.getInputStream(), "src");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    imgCache.put(link, image[0]);
                    return image[0];
                }

                @Override
                protected void onPostExecute(Drawable result) {
                    progressBar.setVisibility(View.INVISIBLE);
                }
            }.execute();
        }
        return image[0];
    }
}

问题是什么?

在我打开Activity所有ListView图像后开始加载。但是加载完成后它们不会显示。它看起来像:

在此处输入图像描述

然后我尝试向下滚动 2 个项目,然后返回到之前的位置。完成此操作后,我可以看到 2 个带有图像的上部项目。当我滚动到它们时,也可以看到所有向下的图像。

在此处输入图像描述

4

3 回答 3

2

根据您的问题,您似乎需要ListView在下载图像后刷新您的图像(因为当您滚动时它们确实会出现):

adapter.notifyDataSetChanged();
于 2013-04-16T14:43:05.613 回答
2

AsyncTask是异步的,因此您的应用程序的流程是:

ListView Item 需要显示 -> 为 List item 调用 Adapter.getView(...) -> 如果图像不在缓存中,则执行 AsyncTask 并返回(不等待结果)所以,当您向下滚动和返回时,再次调用 Adapter.get(...) 方法,但是这次图像在缓存中,因此它返回显示的 Drawable 对象

解决此问题的一种方法是从 AsyncTask 对 Adapter 进行回调,该回调将在调用notifyDataSetChangedAdapter 检索图像后更新图像,直接设置特定的 Drawable 或类似的东西(同时显示图像的加载 gif? )

或者

调用 AsyncTaskget(long timeout, TimeUnit unit)方法,该方法将阻塞人线程并等待 AsyncTask 完成。完成后,它将返回结果(在这种情况下是您的 Drawable)。这将导致主 UI 线程在获取图像时挂起,因此不是解决此问题的最佳方法。

于 2013-04-16T14:52:52.290 回答
1

问题是您的视图加载并填充了您的列表 OnCreate,但当时您的异步任务尚未返回您的列表,因此当 getView 调用您的缓存时它是空的,由于 android View Recycling 当您滚动它时再次调用 getView,这填充缓存的时间。

我建议您NotifyDataSetChanged在 ListView 适配器上调用 onPostExecute,这将在您拥有图像后强制重绘。

于 2013-04-16T14:44:26.163 回答