Android 在ListView中异步加载图像时遇到问题

Android 在ListView中异步加载图像时遇到问题,android,listview,parse-platform,android-arrayadapter,Android,Listview,Parse Platform,Android Arrayadapter,这对我来说是一个很大的麻烦,我已经为此工作了好几个小时了,没有任何线索 我发现ListView中的异步图像加载有问题 我使用Parse.com作为应用程序的后端,从Parse.com类检索消息及其图像 一切正常,当我上/下滚动或再次加载列表视图时,图片混合,所有图片以另一个顺序重新加载,几秒钟后它们将按我想要的顺序进行排序,但这对我来说是个大问题 我想这是因为我使用这样的类来上传图像 private class DownloadImageTask extends AsyncTask<Str

这对我来说是一个很大的麻烦,我已经为此工作了好几个小时了,没有任何线索

我发现ListView中的异步图像加载有问题

我使用Parse.com作为应用程序的后端,从Parse.com类检索消息及其图像

一切正常,当我上/下滚动或再次加载列表视图时,图片混合,所有图片以另一个顺序重新加载,几秒钟后它们将按我想要的顺序进行排序,但这对我来说是个大问题

我想这是因为我使用这样的类来上传图像

private class DownloadImageTask extends AsyncTask<String, Void, Bitmap>
下面是我如何将项目添加到列表中:

contacts c = new contacts();
            c.setName(object.get("name").toString());
            c.setNumero(object.get("phone").toString());
            ParseFile image = (ParseFile)object.get("Profil");
            c.setProfil(image.getUrl());
            messagelist.addcontact(c);
这是我如何从MainActivity填充列表视图的代码:

        adapterview adapter = new adapterview(MainActivity.this, (ArrayList<Message>) messagelist);
    list.setAdapter(adapter);
adapterview adapter=newadapterView(MainActivity.this,(ArrayList)messagelist);
list.setAdapter(适配器);
这里有两个屏幕截图,当我向下滚动然后向上滚动时,第一个列表项的图片会发生变化!!然后在几秒钟后回到正常画面


如果你能建议一种新方法,让我可以将图片从URL上传到ImageView,那就太好了。

上次我还使用了手动下载联系人的头像,但这很糟糕。 你的问题我想:

  • 下载化身,然后设置为ImageView
  • 但是,您使用的是ViewHolder模式,因此新下载的头像将针对指定联系人设置为many imageview>error avatar(这仅在下载所有头像时运行良好)
首先,检查通用图像加载器库,将头像URL设置为视图,它将自动下载,并将您的头像缓存到内存中


如果您仍然遇到错误的头像问题,请在此发布。

什么是listview单元格布局xml文件? 我认为Android无法确定listview的单元格大小。这导致了一些问题。 如果要使用异步加载图像,解决此问题的一种方法是修复图像大小。比如说

    <ImageView
        android:id="@+id/row_icon1"
        android:layout_width="60dip"
        android:layout_height="60dip"
        android:layout_gravity="center_vertical"
    />

图片混合,所有图片以另一顺序重新加载,以及 几秒钟后,他们将按我的要求点菜

这种奇怪的行为是由于
getView
方法中的
AsyncTask
没有视图持有者模式而导致的

要避免再次渲染已渲染的缩略图图像,并在滚动的listview中从网络加载新图像,请使用视图保持器模式

请参阅以下有用的教程,以创建具有良好滚动效果的ListView,并使用View Holder加载性能:


我认为您所观察到的是listview的viewholder模式。您正试图通过getview()中的aysnctask下载图像并将其设置为图像但是,当您上下滚动视图时,视图会被回收,当您再次转到该位置时,getview会调用该位置,因此asynctask会再次执行,它会再次下载设置,并在imageview中设置图像,因此您会看到延迟,我建议你使用PICASSOLibrarray from square它对图像下载和缓存图像非常有效这里是谷歌官方推荐的链接或使用Glide,这里是github链接,因为在滚动时ListView会回收视图,然后,当调用异步任务下载图片并滚动时,下载完成,但引用指向一个循环视图和一个或多个指向同一视图的异步任务。一种可以避免这种情况的方法是在下载开始时查看标签,在下载结束时,在绘制图像之前检查实际参考是否正确,然后绘制图像

您可以使用图像的URL标记视图,因为它是唯一的值

在下载的预执行过程中,必须使用URL(字符串)标记ImageView

当任务完成时,在绘制图像之前,恢复标记并检查它

String tag = (String)imageView.getTag();
if(tag != null && tag.equals(url)){
    //Draw the image
} else {
    //Draw the placeholder or clean the ImageView
}
您可以使用ViewHolder模式升级ListView的性能,以及为什么在Parse可以通过API执行时手动下载图像,对于解析方式和使用缓存策略,在下载图像时自动缓存位图,以及在再次请求下载时检索缓存结果


干杯

我使用回收视图的
onBindViewHolder解决了这个问题

@Override
public void onBindViewHolder(final MyViewHolder viewHolder, int i) {
    CartsViewModel currentData = data.get(i);
    ParseFile image = currentData.getParseImage();
    if(image!=null){
        Log.d(TAG,"image not null. Downloading....");
        image.getDataInBackground(new GetDataCallback() {
            @Override
            public void done(byte[] bytes, ParseException e) {
                if(e==null){
                    Log.d(TAG,"donload finished");
                    Bitmap bmp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
                    viewHolder.cartImage.setImageBitmap(bmp);
                }else{
                    viewHolder.cartImage.setImageBitmap(null);
                }
            }else{
                viewHolder.cartImage.setImageBitmap(null);
            }
        });
    }
    viewHolder.cartName.setText(currentData.getCartName());
    viewHolder.cartAddress.setText(currentData.getCartAddress());
    viewHolder.rating.setText(currentData.getRating());
    viewHolder.reviewCount.setText(currentData.getReviewCount());

}

与parse方法的工作方式类似

你能详细说明我该怎么做你说的吗??你能给我一个指导吗source@NadadorBaseBase乐于帮助我解决了调用
viewHolder.cartImage.setImageBitmap(null)的问题加载前
imageView.setTag(url);
String tag = (String)imageView.getTag();
if(tag != null && tag.equals(url)){
    //Draw the image
} else {
    //Draw the placeholder or clean the ImageView
}
@Override
public void onBindViewHolder(final MyViewHolder viewHolder, int i) {
    CartsViewModel currentData = data.get(i);
    ParseFile image = currentData.getParseImage();
    if(image!=null){
        Log.d(TAG,"image not null. Downloading....");
        image.getDataInBackground(new GetDataCallback() {
            @Override
            public void done(byte[] bytes, ParseException e) {
                if(e==null){
                    Log.d(TAG,"donload finished");
                    Bitmap bmp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
                    viewHolder.cartImage.setImageBitmap(bmp);
                }else{
                    viewHolder.cartImage.setImageBitmap(null);
                }
            }else{
                viewHolder.cartImage.setImageBitmap(null);
            }
        });
    }
    viewHolder.cartName.setText(currentData.getCartName());
    viewHolder.cartAddress.setText(currentData.getCartAddress());
    viewHolder.rating.setText(currentData.getRating());
    viewHolder.reviewCount.setText(currentData.getReviewCount());

}