【问题标题】:ImageViews which is in ListView doesn't displayedListView 中的 ImageViews 不显示
【发布时间】:2013-04-16 14:39:10
【问题描述】:

我有带有 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];
    }
}

问题是什么?

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

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

【问题讨论】:

  • 只是一个警告:HashMap&lt;String, Drawable&gt; 取决于您拥有的可绘制对象数量以及用户使用的设备,您的应用会出现 OutOfMemory 错误。
  • 我可以得到这个 HashMap 的大小吗?缓存的大小必须是多少?
  • 用于图像缓存(我通常使用Bitmap,但Drawable也一样)我建议你使用LruCache(developer.android.com/reference/android/support/v4/util/…)

标签: android listview caching android-asynctask android-imageview


【解决方案1】:

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

adapter.notifyDataSetChanged();

【讨论】:

  • 我也想了想,但是这条线我必须在哪里调用呢?
【解决方案2】:

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

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

解决此问题的一种方法是从 AsyncTask 回调到 Adapter同时为图像?)

或者

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

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-08
      • 2017-08-02
      • 1970-01-01
      相关资源
      最近更新 更多