3

我需要在列表视图中显示一些照片,这些照片是从列表视图中的 url 中提取的。不幸的是,下载时间存在一些差异。实际下载是在 ListView 的适配器中完成的。这些下载是runOnUIThread。(是的,我知道这是可怕的设计)。所以发生的事情是下载完成时正在显示图像,这导致图像显示缓慢且有点混乱,尽管我正在缓存它们。

我打算重写逻辑,但与此同时,我想知道在实际需要显示照片之前让适配器采取行动。换句话说,我想在我真正打算向用户显示列表之前运行适配器。我怎样才能做到这一点?我希望在用户看到列表之前进行此下载。

换句话说,我需要在用户可以看到列表之前运行适配器中的以下方法:

 public View getView(final int position, View convertView, ViewGroup parent) 
 {
     // Inside here I am requesting the photo bitmap from url and setting to ImageView.
 }
4

4 回答 4

4

选项 1:在适配器的构造函数中预加载

在适配器的构造函数中,遍历集合列表并将图像发送到您的图像下载器以开始下载。您可以从前 5-10 个开始,或者最多 50 个。如果您的用户可能使用手机,请注意他们的带宽速度/成本,并将您的预加载限制在 20 个左右。

/** Constructor of MyAdapter extends ArrayAdapter<Item> */
public MyAdapter(Context context, List<Item> items) {
  super(context, 0, items);

  int limit = Math.min(10, items.size());
  for (int i = 0; i < limit; i++) {
    // don't fetch by position if `items` doesn't support random access
    AsyncImageLoader.prefetchImage(items.get(i).getImageUrl());
  }
}

-和/或-

选项 2:加载一行时,预加载接下来的几行

在adapter的getView中,预加载下几个item的图片;例如

public View getView(int position, View convertView, ViewGroup parent) {
  int limit = Math.min(position + 4, getCount());
  for (int i = position; i < limit; i++) {
    AsyncImageLoader.prefetchImage(getItem(i).getImageUrl());
  }
}
于 2012-11-09T09:36:40.087 回答
3

实际上,您的列表视图中有getAdaptersetAdapter接口。在您的情况下,更好的主意是预先创建适配器(创建您自己的BaseAdapter)并告诉它开始下载图像。当您决定显示您的列表视图时 - 只需调用setAdapter并传递您的适配器。

顺便说一句,每当您有新数据时,请不要忘记notifyDataSetChanged()从您的适配器调用。另请注意,所有数据更新都应在 ui 线程中进行;)

这是您设计的最简单解决方案:)。让我知道您对其他选项感兴趣。

于 2012-07-27T23:31:56.283 回答
1

您可以使用picasso 库为 android。这是一个很好的图片下载库。您可以使用此代码在适配器中预加载图像。

public View getView(int position, View convertView, ViewGroup parent) {

  // Create your view here

  int lastImagePosition = Math.min(position + 4, getCount());

  for (int i = position + 1; i < lastImagePosition; ++i) {
    Picasso.with(getContext()).load(getItem(i)); //getItem() - if your adapter data are image urls
  }

  return createdView;
}
于 2014-10-07T07:05:08.363 回答
-1

Frescolib 是列表视图中图像的最佳解决方案。如果您只想下载图像并显示它,Fresco 将显示一个占位符,直到它出现。 http://frescolib.org/docs/getting-started.html#_

看看实现起来有多容易。

在您的 XML 中,将自定义命名空间添加到顶级元素

<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:fresco="http://schemas.android.com/apk/res-auto"
    android:layout_height="match_parent"
    android:layout_width="match_parent">

然后将 SimpleDraweeView 添加到布局中

<com.facebook.drawee.view.SimpleDraweeView
    android:id="@+id/my_image_view"
    android:layout_width="130dp"
    android:layout_height="130dp"
    fresco:placeholderImage="@drawable/my_drawable"
  /> 

要显示图像,您只需执行以下操作:

Uri uri = Uri.parse("https://raw.githubusercontent.com/facebook/fresco/gh-pages/static/fresco-logo.png");
SimpleDraweeView draweeView = (SimpleDraweeView) findViewById(R.id.my_image_view);
draweeView.setImageURI(uri);

Fresco 完成剩下的工作。

占位符会一直显示,直到图像准备好。当您的视图离开屏幕时,图像将被下载、缓存、显示并从内存中清除。

于 2015-08-13T06:40:14.227 回答