如何将图像加载到列表视图适配器中的正确行
How to load image into the correct row in a list view adapter
在以下情况下:除了使用 AsyncTask,我还有什么替代方法?
我正在使用 AsyncTask 将图像加载到适配器中。适配器行有多个 TextView 和一个 ImageView。 ImageView 是我加载图像的地方。图片正在从互联网上加载。问题是,当我滚动时,错误的图像会显示在 row/cell 中——直到正确的图像有时间到达。如何防止这种图像不匹配的情况发生? 我问这个问题是因为我想了解它是如何工作的:我不只是想要一些可以为我完成工作的库(我已经尝试过的许多库,有失败)。
问题又来了: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);
}
最常见的方法是使用您在适配器中创建的视图的 setTag(...) 和 getTag(...) 方法。创建后,您可以将需要 link 的标签添加到随后异步加载的图像中。该任务完成后,您可以检查视图的标签,如果它仍然与异步任务启动时相同,您可以设置图像。否则你可以关闭图像。请记住,当您滚动时,相同的视图会被重新使用而不是创建。所以标签会改变。
问题是行被回收,图像视图也是如此。然后当服务器响应 returns 图像视图已经属于另一个数据对象。
对此有不同的方法。我的解决方案是扩展 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)
我还建议您将其与位图缓存结合使用,以加快获取图像和添加占位符的过程:)
在以下情况下:除了使用 AsyncTask,我还有什么替代方法?
我正在使用 AsyncTask 将图像加载到适配器中。适配器行有多个 TextView 和一个 ImageView。 ImageView 是我加载图像的地方。图片正在从互联网上加载。问题是,当我滚动时,错误的图像会显示在 row/cell 中——直到正确的图像有时间到达。如何防止这种图像不匹配的情况发生? 我问这个问题是因为我想了解它是如何工作的:我不只是想要一些可以为我完成工作的库(我已经尝试过的许多库,有失败)。
问题又来了: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);
}
最常见的方法是使用您在适配器中创建的视图的 setTag(...) 和 getTag(...) 方法。创建后,您可以将需要 link 的标签添加到随后异步加载的图像中。该任务完成后,您可以检查视图的标签,如果它仍然与异步任务启动时相同,您可以设置图像。否则你可以关闭图像。请记住,当您滚动时,相同的视图会被重新使用而不是创建。所以标签会改变。
问题是行被回收,图像视图也是如此。然后当服务器响应 returns 图像视图已经属于另一个数据对象。
对此有不同的方法。我的解决方案是扩展 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)
我还建议您将其与位图缓存结合使用,以加快获取图像和添加占位符的过程:)