如何将图像加载到列表视图适配器中的正确行

时间:2015-03-13 18:56:14

标签: android image listview android-asynctask adapter

在以下情况中:使用AsyncTask的替代方法是什么?

我正在使用AsyncTask将图像加载到适配器中。适配器行有许多TextView和一个ImageView。 ImageView是我加载图像的地方。图像正在从互联网上加载。问题是,当我滚动时,错误的图像将显示在行/单元格中 - 直到正确的图像有时间到达。如何防止此图像不匹配? 我问的是这个问题,因为我想了解它是如何工作的:我不只是想得到一些可能为我工作的库(我已经尝试过许多库,但都失败了)。

问题再次出现:AsyncTask导致图像加载到错误的行中,以便用户可以清楚地看到图像正在寻找最终目的地。

我希望问题很清楚。为了完整性,下面是我在适配器的getView方法内调用以加载每个图像的方法。该方法也在适配器内部。 使用AsyncTask的替代方法是什么?

private void loadImage(final ImageView photo, String imageUrl) {
        new AsyncTask<String, String, Bitmap>() {

            @Override
            protected Bitmap doInBackground(String... param) {
                try {
                    Bitmap b = callToServer(imageUrl);//takes long
                    return b;
                } catch (Exception e) {
                    e.printStackTrace();
                    return null;
                }
            }

            @Override
            protected void onPostExecute(Bitmap ret) {
                if (ret != null) {
                    photo.setImageBitmap(ret);
                }
            }

        }.execute(imageUrl);

    }

2 个答案:

答案 0 :(得分:4)

最常用的方法是使用您在适配器中创建的视图的setTag(...)和getTag(...)方法。创建后,添加一个标记,您需要将该标记链接到随后异步加载的图像。完成该任务后,您可以检查视图的标记,如果它仍然与异步任务启动时相同,则可以设置图像。否则你可以解雇图像。请记住,滚动时会重复使用相同的视图而不是创建的视图。那么标签就会改变了。

这是一个很好的例子:Asynchronous Image Loader in Android ListView

答案 1 :(得分:1)

问题是行被回收,图像视图也被回收。然后当服务器响应返回时,图像视图已经属于另一个数据对象。

有不同的方法。我的解决方案是扩展ImageView并跟踪您要加载的图像。

class RemoteImageView extends ImageView {
   private String _uri;

   public synchronized void loadRemoteImage(String uri) {
       _uri = uri;
       loadImage(this, uri) ; //this is your async call
   }

  private synchronized void onImageLoaded(String uri, Bitmap image) {
       if(uri.equals(_uri)) {  //this will set only the correct image
            setImageBitmap(image);
       }
  } 

}

关于你的加载功能:

private void loadImage(final ImageView photo, final String imageUrl) {
        new AsyncTask<String, String, Bitmap>() {

            @Override
            protected Bitmap doInBackground(String... param) {
                try {

                    Bitmap b = callToServer(imageUrl);//takes long
                    return b;
                } catch (Exception e) {
                    e.printStackTrace();
                    return null;
                }
            }

            @Override
            protected void onPostExecute(Bitmap ret) {
                if (ret != null) {
                    photo.onImageLoaded(imageUri, ret);
                }
            }

        }.execute(imageUrl);

    }

然后使用你的适配器你应该调用loadRemoteImage(imageUri)

我还建议你将它与位图缓存结合起来,以便加速获取图像和添加占位符的过程:)