【问题标题】:NetworkImageView inside RecyclerView sometimes not loading images when scrolling recyclerView list fast. Volley getting slow response from the network快速滚动 recyclerView 列表时,RecyclerView 内的 NetworkImageView 有时无法加载图像。 Volley 网络响应缓慢
【发布时间】:2017-05-22 16:25:20
【问题描述】:

我有一个 RecyclerView。

<android.support.v7.widget.RecyclerView android:id="@+id/recyclerView"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1"/>

我将 CardView 作为我的 RecyclerView 的 listItem

<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
    android:orientation="vertical"
    android:background="@android:color/white"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <com.android.volley.toolbox.NetworkImageView
        android:id="@+id/networkImageView"
        android:adjustViewBounds="true"
        android:scaleType="fitXY"
        android:layout_width="match_parent"
        android:layout_height="130dp"/>
</android.support.v7.widget.CardView>

在 recyclerAdapter 的 onBindViewHolder 中,我正在使用网络上的图像加载 NetworkImageView

ImageLoader imageLoader =    RequestUtil.getInstance(_context).getImageLoader();
    String imageUrl = "http://someinterneturl/asdfaas/dsawes.png"; // I get these URL for images from a service.
    networkImageView.setImageUrl(imageUrl,imageLoader);

我有 RequestUtil 类,从那里我得到我的 ImageLoader

public class RequestUtil {

private static RequestUtil _instance;
private RequestQueue _requestQueue;
private static Context _ctx;
private ImageLoader _ImageLoader;
private static final String DEFAULT_CACHE_DIR = "volley";
private static final int DEFAULT_NETWORK_THREAD_POOL_SIZE = 8;

private RequestUtil(Context context) {
    _ctx = context;
}

public static synchronized RequestUtil getInstance(Context context) {
    if(_instance == null) {
        _instance = new RequestUtil(context);
    }

    return _instance;
}

public RequestQueue getRequestQueue() {
    if(_requestQueue == null) {
        //_requestQueue = Volley.newRequestQueue(_ctx.getApplicationContext());
        _requestQueue = getNewRequestQueue();
    }

    return _requestQueue;
}

public <T> void addToRequestQueue(Request<T> request) {
    getRequestQueue().add(request);
}

public ImageLoader getImageLoader() {

    if (_ImageLoader == null) {
        _ImageLoader = new ImageLoader(this.getRequestQueue(),
                new LruBitmapCacheUtil());
    }
    return this._ImageLoader;
}

private RequestQueue getNewRequestQueue(){
    Context context = _ctx.getApplicationContext();
    File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);
    HttpStack stack= new HurlStack();
    Network network = new BasicNetwork(stack);
    RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network,DEFAULT_NETWORK_THREAD_POOL_SIZE);
    queue.start();
    return queue;

}

}

这很好用,但是当我快速滚动RecyclerViewList 时,有时屏幕上的一个NetworkImageView 不会加载图像。我在 android studio 中看到以下几个日志

W/art: Long monitor contention with owner Thread-6 (8925) at com.android.volley.Response com.android.volley.toolbox.ImageRequest.parseNetworkResponse(com.android.volley.NetworkResponse)(ImageRequest.java:124) waiters=5 in com.android.volley.Response com.android.volley.toolbox.ImageRequest.parseNetworkResponse(com.android.volley.NetworkResponse) for 279ms

大多数情况下,即使是显示的这些图像,我也会看到以下日志。

D/Volley: [416] BasicNetwork.logSlowRequests: HTTP response for request=<[ ] "http://someinterneturl/asdfaas/dsawes.png" 0xe48e98af LOW 249> [lifetime=10978], [size=867672], [rc=200], [retryCount=2]

请通过在滚动停止时加载所有图像并从日志中删除上述两个警告来帮助我解决此问题。如果您需要更多信息,请与我们联系。

【问题讨论】:

  • 当viewholder被回收时,如果图像加载还没有开始(或完成),你应该取消它。当您快速滚动时,所有项目都在请求图像加载,即使其中许多不再需要显示,它也会让您的队列充满请求。

标签: android android-recyclerview android-volley networkimageview


【解决方案1】:

我在之前的项目中遇到了同样的问题,并用 Picasso 替换了 volley 库。

它就像一个魅力,它具有出色的将下载的图像映射到相应的视图以及优化的缓存技术。

请参阅http://square.github.io/picasso/ 以了解用法和完整教程。

希望对你有帮助。

【讨论】:

    【解决方案2】:

    不要使用 NetworkImageView。 NetworkImageView 是一个不错的捷径,但它不够灵活。通过自己进行加载,您可以通过 ImageRequest 或 ImageLoader 控制图像的加载。例如,如果您检测到回收器视图正在快速滚动,您可以停止发出请求,直到它停止为止。但是 NetworkImageView 是为最简单的情况编写的——它假定您真的想要图像并立即加载它而无需取消。将其用于您不回收的物品。

    【讨论】:

      【解决方案3】:

      您应该在 recyclerview 中预取图像,这样当您快速滚动时,图像会立即出现。有很多方法可以做到,但没有一个是容易的。 Glide 有关于如何在 recyclerview 中预取图像的示例:https://github.com/bumptech/glide/tree/master/integration/recyclerview

      【讨论】:

      • 这对于包含少量项目的回收站视图是不实用的。内存不是免费的。即使您只预取到磁盘,磁盘空间也不是空闲的。您可以预取接下来的几个项目,但快速滚动会超过您实际可以下载的数量。
      • 如果你使用 Glide,它会处理内存问题。
      猜你喜欢
      • 1970-01-01
      • 2017-04-09
      • 1970-01-01
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多