当我点击其他屏幕元素时,如何防止Android listview中的图像四处移动?

当我点击其他屏幕元素时,如何防止Android listview中的图像四处移动?,android,android-listview,android-asynctask,Android,Android Listview,Android Asynctask,早些时候我发表了另一篇关于这个主题的文章,但后来我根据建议对代码做了一些修改,但同样的问题也存在。如果我点击屏幕上的其他元素,我的图像就会不断变换 这是我的代码,我通过以下方式调用: 新的缩略图程序(image\u main,image\u table)。执行(image) image_main是我的imageView,image_table是保存它的表 private class Thumbnailer extends AsyncTask<String, Void, Bitmap>

早些时候我发表了另一篇关于这个主题的文章,但后来我根据建议对代码做了一些修改,但同样的问题也存在。如果我点击屏幕上的其他元素,我的图像就会不断变换

这是我的代码,我通过以下方式调用:

新的缩略图程序(image\u main,image\u table)。执行(image)

image_main是我的imageView,image_table是保存它的表

 private class Thumbnailer extends AsyncTask<String, Void, Bitmap> {
      private ImageView imageView;
      private TableLayout imageTable;

        public Thumbnailer(ImageView imageView, TableLayout imageTable) {
            this.imageView = imageView;
            this.imageTable = imageTable;
        }

  @Override
  protected void onPostExecute(Bitmap result) {
      imageView.setImageBitmap(result);
               imageView.setVisibility(View.VISIBLE);
               imageTable.setVisibility(View.VISIBLE);
  }
  @Override
      protected void onProgressUpdate(Void... progress) {
      }

  @Override
  protected Bitmap doInBackground(String... params) {
         BitmapFactory.Options o = new BitmapFactory.Options();
          o.inJustDecodeBounds = true;
          BitmapFactory.decodeFile(params[0], o);
          final int REQUIRED_SIZE=70;

          //Find the correct scale value. It should be the power of 2.
          int width_tmp=o.outWidth, height_tmp=o.outHeight;
          int scale=1;
          while(true){
              if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
                  break;
              width_tmp/=2;
              height_tmp/=2;
              scale++;
          }
          //Decode with inSampleSize
          BitmapFactory.Options o2 = new BitmapFactory.Options();
          o2.inSampleSize=scale;       
          return BitmapFactory.decodeFile(params[0], o2);
  }
 }
private类Thumbnailer扩展异步任务{
私人影像视图;
私有表布局图像表;
公共缩略图程序(ImageView ImageView、TableLayout imageTable){
this.imageView=imageView;
this.imageTable=imageTable;
}
@凌驾
受保护的void onPostExecute(位图结果){
设置图像位图(结果);
设置可见性(View.VISIBLE);
imageTable.setVisibility(View.VISIBLE);
}
@凌驾
受保护的void onProgressUpdate(void…progress){
}
@凌驾
受保护位图doInBackground(字符串…参数){
BitmapFactory.Options o=新的BitmapFactory.Options();
o、 inJustDecodeBounds=true;
BitmapFactory.decodeFile(参数[0],o);
所需的最终int_尺寸=70;
//找到正确的刻度值。它应该是2的幂。
内部宽度=o.向外宽度,高度=o.向外高度;
int标度=1;
while(true){

如果(width_tmp/2听起来像是你被视图循环所困扰。也就是说,当你在Android中滚动列表时,它不会创建新行,而是重用屏幕外的行。在这种情况下,可能会导致多个任务试图将图像加载到单个imageview中。实际上,你需要能够知道加载请求是哪一个对于一行,最新的一个将被删除,而取消较早的一个/忽略它们的结果,或者只使用一个库来为您处理这个问题(如)


您还可以在适配器中关闭视图循环(该部分使用方法中的
convertView
参数),但请注意,这将使列表滚动缓慢且不稳定,尤其是在较旧的设备上。

听起来像是您被视图循环占用了。也就是说,当您在Android中滚动列表时,它不会创建新行,而是重复使用屏幕外的行。在这种情况下,可能会导致多个任务试图将图像加载到单个列表中实际上,您需要能够知道哪一个加载请求是一行最近的,并取消较早的加载请求/忽略它们的结果,或者只使用一个库来为您处理(如)


您也可以关闭适配器中的视图循环(这是在方法中使用
convertView
参数的部分),但请注意,这将使列表滚动缓慢且不稳定,尤其是在较旧的设备上。

我遇到了类似的问题。我会通过异步任务将图像加载到列表视图中(这可能通过HTTP获取图像),在加载正确的图像之前的一瞬间,它似乎加载了错误的图像。这就好像Android在HTTP请求完成之前重用了该行,而异步任务有点冲突

上述评论证实了这一点

我通过在异步任务开始之前将图像路径放置在ImageView的标记中,然后在异步任务完成后但在调用setImageBitmap之前检查该标记来修复它

添加以下行:

final String somethingUnique = "put the image path or some other identifier here";
image_main.setTag(somethingUnique);
在这一行之前:

new Thumbnailer(image_main, image_table).execute(image);
现在,在onPostExecute中,检查标记:

// if this does not match, then the view has probably been reused
if (((String)imageView.getTag()).equals(somethingUnique)) {
  imageView.setImageBitmap(result);
}

我也遇到了类似的问题。我会通过一个异步任务(可能通过HTTP获取图像)将图像加载到ListView中,在加载正确的图像之前的一瞬间,它似乎加载了错误的图像。这就好像Android在HTTP请求完成之前重用了该行,而异步任务有点冲突

上述评论证实了这一点

我通过在异步任务开始之前将图像路径放置在ImageView的标记中,然后在异步任务完成后但在调用setImageBitmap之前检查该标记来修复它

添加以下行:

final String somethingUnique = "put the image path or some other identifier here";
image_main.setTag(somethingUnique);
在这一行之前:

new Thumbnailer(image_main, image_table).execute(image);
现在,在onPostExecute中,检查标记:

// if this does not match, then the view has probably been reused
if (((String)imageView.getTag()).equals(somethingUnique)) {
  imageView.setImageBitmap(result);
}

这提供了一个参考项目。只需将项目中的http映像下载代码更改为您的
doInBackground
代码。

这提供了一个参考项目。只需将项目中的http映像下载代码更改为您的
doInBackground
代码。

谢谢您的回复。我当前的实现just在getView中有位图解码,它本身工作正常,但速度慢且滞后。我实际上一直在看这个我想我需要了解并发部分是如何处理的?不是很确定。我的java技能不是很好lol。它比这更有趣。你不能保证最近的调用返回的视图获取某个位置的视图是最终出现在屏幕上的视图。ListView和GridView偶尔会使用一个废料视图进行测量。异步加载的一个简单解决方案是通过适配器位置跟踪加载的元素应该到达的位置,而不是最终的目标视图。ListView.getChildAt(位置-ListView.getFirstVisiblePosition())将始终为您提供位置的正确当前项目视图,假设它在范围内并在屏幕上。(检查0我知道你在说什么,但我只是没有任何运气让它在你链接到的博客文章中工作,相关部分是当在同一个视图上启动新下载时,他们取消ImageView上挂起的下载。他们这样做是因为否则异步任务(可能以任何顺序返回)可能会停止相互之间,尤其是在视图回收方面。(顺便提一下,您在这里推出自己的实现有什么原因吗