NetworkImageView внутри RecyclerView иногда не загружает изображения при быстрой прокрутке списка recyclerView. Залп получает медленный ответ от сети

У меня есть 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

<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>

и в onBindViewHolder recyclerAdapter я загружаю 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

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]

Пожалуйста, помогите мне решить эту проблему, загрузив все изображения, когда прокрутка остановится, и удалив два вышеуказанных предупреждения из журнала. Дайте мне знать, если вам нужна дополнительная информация.


person MS_Tech_Programmer    schedule 08.01.2017    source источник
comment
Когда вьюхолдер перезапускается, вы должны отменить загрузку изображения, если она еще не началась (или не закончилась). Когда вы прокручиваете быстро, все элементы запрашивают загрузку изображения, и ваша очередь заполняет запросы, хотя многие из них больше не нужно показывать.   -  person Karakuri    schedule 08.01.2017


Ответы (3)


Я столкнулся с той же проблемой в своем предыдущем проекте и заменил библиотеку volley на Picasso.

Это работало как шарм, и у него было отличное сопоставление загруженных изображений с соответствующими представлениями, а также оптимизированная техника кэширования.

См. http://square.github.io/picasso/ для использования и полного руководства.

Надеюсь, поможет.

person ChaitanyaAtkuri    schedule 08.01.2017

Не используйте NetworkImageView. NetworkImageView — хороший ярлык, но он негибкий. Выполняя загрузку самостоятельно, вы можете контролировать загрузку изображения через ImageRequest или ImageLoader. Например, если вы обнаружите, что представление ресайклера быстро прокручивается, вы можете прекратить делать запросы, пока оно не остановится. Но NetworkImageView был написан для простейшего случая — он предполагает, что вам действительно нужно изображение, и загружает его немедленно без отмены. Используйте его для вещей, которые вы не перерабатываете.

person Gabe Sechan    schedule 08.01.2017

Вы должны предварительно выбрать изображения в recyclerview, чтобы при быстрой прокрутке изображения появлялись немедленно. Есть много способов сделать это, но ни один из них не является легким. В Glide есть пример предварительной загрузки изображений в recyclerview: https://github.com/bumptech/glide/tree/master/integration/recyclerview

person Abhi Muktheeswarar    schedule 08.01.2017
comment
Это нецелесообразно для представления переработчика с большим количеством элементов. Память не свободна. Даже если вы выполняете предварительную выборку только на диск, дисковое пространство также не будет свободным. Вы можете предварительно загрузить следующие несколько элементов, но быстрая прокрутка превзойдет количество, которое вы можете реально загрузить. - person Gabe Sechan; 08.01.2017
comment
Если вы используете Glide, он позаботится о проблемах с памятью. - person Abhi Muktheeswarar; 08.01.2017