繁体   English   中英

如何在Android ListView中最好地从URL加载图像

How to best load images from URL in Android ListView

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

所以我一直在努力用最好的方式在Android中的ListView中加载图像一段时间。

图像来自服务器,因此可能需要一些时间来加载。 根据我的理解,只有两种方法可以实现这一点:

1 - 在主线程上加载图像 - 这样可以在视图显示和滚动时立即显示正确的图像,但滚动性能较差,并且可能导致应用程序挂起和崩溃。

2 - 在AsyncTask中加载图像。 这意味着当列表显示或滚动时图像将为空白,但最终显示。 由于列表执行缓存,您还可以获取项目的错误图像。 但这会提供良好的性能和滚动,并且不会挂起/崩溃。

似乎两种解决方案都无法正常工作。 必须有一个有效的解决方案?? 我见过这样的其他帖子,但答案似乎总是1或2,但两者都不是一个好的解决方案......

我的列表适配器代码如下。 HttpGetImageAction.fetchImage()方法执行异步任务,或根据我设置的标志在主线程上获取图像。 我还会在加载后在本地和磁盘上缓存图像,因此问题主要发生在第一次(但缓存仅适用于100个图像,列表有1000个)

public class ImageListAdapter extends ArrayAdapter<WebMediumConfig> {

Activity activity;

public ImageListAdapter(Activity activity, int resourceId, List<WebMediumConfig> items) {
    super(activity, resourceId, items);
    this.activity = activity;
}

class ImageListViewHolder {
    ImageView imageView;
    TextView nameView;
    TextView descriptionView;
    TextView statView;
}

public View getView(int position, View convertView, ViewGroup parent) {
    ImageListViewHolder holder = null;
    WebMediumConfig config = getItem(position);

    LayoutInflater mInflater = (LayoutInflater)this.activity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.image_list, null);
        holder = new ImageListViewHolder();
        holder.imageView = (ImageView)convertView.findViewById(R.id.imageView);
        holder.nameView = (TextView) convertView.findViewById(R.id.nameView);
        holder.descriptionView = (TextView)convertView.findViewById(R.id.descriptionView);
        holder.statView = (TextView)convertView.findViewById(R.id.statView);
        convertView.setTag(holder);
    } else {
        holder = (ImageListViewHolder) convertView.getTag();
    }

    holder.nameView.setText(Utils.stripTags(config.name));
    holder.descriptionView.setText(Utils.stripTags(config.description));
    holder.statView.setText(config.stats());
    if (MainActivity.showImages) {
        HttpGetImageAction.fetchImage(this.activity, config.avatar, holder.imageView);
    } else {
        holder.imageView.setVisibility(View.GONE);
    }

    return convertView;
  }
}
9 个回复

你永远不应该在主线程上加载图像。 任何网络调用都应该异步完成,不应该在主线程上完成。 您的图像可能会快速加载(在主线程上),因为您可能具有良好的互联网连接,图像较小和/或图像很少。 但想象一下,如果有人使用你的应用程序有一个较慢的互联网,然后有一天你的列表增长到数百!

下面的方法是加载scrollview内容的公认惯例

  • a)在加载scrollview时加载文本内容。 再次加载应该是异步的,但您可以显示加载视图,直到下载完成
  • b)在每个单元格上加载图像时显示图像占位符
  • c)异步加载图像

使用像毕加索这样的库会有很大的帮助,因为你需要处理很多样板代码,例如

  • 在重复使用单元格时取消图像下载
  • 为重用的单元格开始新的下载
  • 高速缓存
  • 重试失败的下载

希望这可以帮助。

使用Glide [ https://github.com/bumptech/glide]或Picasso [ http://square.github.io/picasso/] - 这两个库非常相似,易于使用,有缓存,后台工作,允许占位符ets。 用法很简单:

Picasso.get().load("http://i.imgur.com/DvpvklR.png").into(imageView);

简单的解决方案:滑翔。

Glide是一款快速高效的Android开源媒体管理和图像加载框架,它将媒体解码,内存和磁盘缓存以及资源池包装成简单易用的界面。 Glide支持提取,解码和显示视频静止图像,图像和动画GIF。

您可以加载图像,如:

GlideApp.with(context)
    .load("http://via.placeholder.com/300.png")
    .into(imageView);

请参阅更多信息:

https://guides.codepath.com/android/Displaying-Images-with-the-Glide-Library https://github.com/bumptech/glide

使用Glide库..由Google推荐。

步骤1:

使用最新的Glide Version 4依赖( https://github.com/bumptech/glide

实现'com.github.bumptech.glide:glide:4.8.0'

annotationProcessor'com.github.bumptech.glide:compiler:4.8.0'

第2步:

 Glide.with(MainActivity.this)
        .load(url)
        .apply(new RequestOptions().placeholder(R.drawable.placeholder).error(R.drawable.error_image))//this line optional - you can skip this line
        .into(imageview);

使用毕加索或Glide库这些库的作用是,它们从u中成像并下载它们并将其保存在缓存中,以便每次打开相同的图像时它会加载更快并且它会阻止网络的使用

毕加索http://square.github.io/picasso/

Glide https://github.com/bumptech/glide

您可以尝试UnivarsalImageLoader,它非常快速和优化。 它支持多线程图像加载(异步或同步)和高级别的自定义。

https://github.com/nostra13/Android-Universal-Image-Loader

这是我如何做到的

首先,我总是创建我传递Func<int, Bitmap> image_provider image_provider的RecyclerView.ViewHolder(或者你可以传递某种lamda?),当调用它时将检索特定Id的图像,如果它不能显示默认加载图像

所有内容都存储在一个片段(我称之为DataFragment)中,该片段将retainstate设置为true。

首先加载一个json对象列表,告诉我必须显示哪些图像,这发生在数据片段内部,因此如果有配置更改它将继续

我使用像SetItems(MyImages)这样的方法将该信息发送到适配器

然后我开始一个新的线程,将加载图像(同时允许用户工作)

我用TPL库做到这一点,最接近Android的近似是Anko Async,但你也可以用AsyncTask做,问题是我向主线程发送了很多消息,所以要用AsyncTask做你必须给它它是主线程的处理程序,它将发送消息。

在线程中,我遍历我必须下载的所有图像,并下载它们并向DataFragment发送消息,DataFragment将消息发送到当前连接的Activity,该Activity触发适配器中的NotifyItemChanged方法

创建时的适配器接收一个Func<int, Bitmap> image_provider ,它调用并从内存中检索图像

我知道这听起来有点乱,所以如果你想要代码示例我可以给它们,但它们在C#中

在您的应用程序级别gradle实现下面的存储库:

implementation 'com.squareup.picasso:picasso:2.5.2'

放在要加载图像的行下方

 Picasso.with(getApplicationContext()).load(config.avatar).into(imageview);

只需使用Picasso.get()。load(“ http://i.imgur.com/DvpvklR.png ”)。into(imageView); 或者Glide.with(getApplicationContext())。load(“image_url”)。asBitmap()。centerCrop()。into(new BitmapImageViewTarget(imageView)

在适配器中像任何视图一样,并且不需要额外的努力

1 如何在Android Studio中最好地实现图像加载系统

底线是这个。 有需要从Firebase存储下载其图像的用户列表。 所有图像的下载都是不合理的,因为大量用户不可避免地会遇到存储问题。 问题:在这种情况下应怎么做才能最合理地实现此功能? ...

2017-05-21 17:11:47 1 33   android
5 Android将URL中的图像加载到ListView中

我有一个ListView,我想从其中图像名称为ID.jpg的URL加载图像(例如:1.jpg / 2.jpg / 3.jpg ..等)。 这些ID来自数据库,但是加载到我的ListView中所有行的图像都是一张图像(1.jpg)。 request_eventID是来自数据库的ID,这是 ...

2016-03-31 19:56:59 1 38   android
8 将图像从URL加载到ListView

我正在尝试制作列表视图。 我成功完成了此操作,而没有使用自定义数组适配器从url加载照片。 但是,如何在不使用自定义数组适配器的情况下实现从url加载图像? 我正在尝试使用此线程中的工作代码,但它给Holder提供了错误。 错误部分 DoctorsActivity.jav ...

10 Android从URL设置ListView图像

我有一个包含图片的Newsfeed(ListView)。 我想从网络上加载图像并用于我的活动中。 所以我在MainActivity的OnCreate()中有这个: 这是我的FeedUser.java 下面是FeedUser适配器: 现在它没有显示任何错误,但是图像也不 ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2022 STACKOOM.COM