Android技术进阶Android技术知识Android开发经验谈

ListView图片加载讲解

2015-10-19  本文已影响572人  alighters

在ListView加载图片的时候,我们就会关于这里的图片加载产生一些问题。另外,我们知道针对ListView加载图片常用的优化方案之一就是,在列表的滑动过程中,暂停图片的加载任务,在滑动结束之后,则继续之前的任务。所以我们针对这些问题进行一些探讨研究(以UIL图片加载为例)。

private final AtomicBoolean paused = new AtomicBoolean(false);

private final Object pauseLock = new Object();

/**
 * Pauses engine. All new "load&display" tasks won't be executed until ImageLoader is {@link #resume() resumed}.Already running tasks are not paused.
 */
void pause() {
    paused.set(true);
}

/** Resumes engine work. Paused "load&display" tasks will continue its work. */
void resume() {
    paused.set(false);
    synchronized (pauseLock) {
        pauseLock.notifyAll();
    }
}
  
AtomicBoolean getPause() {
    return paused;
}

Object getPauseLock() {
    return pauseLock;
}
 ```
 在LoadAndDisplayImageTask的方法中,执行图片的加载的时候,会进行pause的判断。
```java

 /** @return <b>true</b> - if task should be interrupted; <b>false</b> - otherwise */
private boolean waitIfPaused() {
    AtomicBoolean pause = engine.getPause();
    if (pause.get()) {
        synchronized (engine.getPauseLock()) {
            if (pause.get()) {
                L.d(LOG_WAITING_FOR_RESUME, memoryCacheKey);
                try {
                    engine.getPauseLock().wait();
                } catch (InterruptedException e) {
                    L.e(LOG_TASK_INTERRUPTED, memoryCacheKey);
                    return true;
                }
                L.d(LOG_RESUME_AFTER_PAUSE, memoryCacheKey);
            }
        }
    }
    return isTaskNotActual();
}
  ```
 另外,pause跟resume的调用,则是在UIL的PauseOnScrollListener进行滑动判断的调用。所以可以明显的看出是通过object的wait跟notifyAll实现线程同步,来达到暂停图片加载的任务的。
```java

/** @return <b>true</b> - if current ImageAware is reused for displaying another image; <b>false</b> - otherwise */
private boolean isViewReused() {
String currentCacheKey = engine.getLoadingUriForView(imageAware);
// Check whether memory cache key (image URI) for current ImageAware is actual.
// If ImageAware is reused for another task then current task should be cancelled.
boolean imageAwareWasReused = !memoryCacheKey.equals(currentCacheKey);
if (imageAwareWasReused) {
L.d(LOG_TASK_CANCELLED_IMAGEAWARE_REUSED, memoryCacheKey);
return true;
}
return false;
}

而在调用isViewReused的checkViewReused的如下,
```java
/** @throws TaskCancelledException if target ImageAware is collected by GC */
 private void checkViewReused() throws TaskCancelledException {
     if (isViewReused()) {
         throw new TaskCancelledException();
     }
 }

最后,在线程的主体run方法中,通过调用checkTaskNotActual()判断view重用或者被回收,抛出TaskCancelledException,来结束当前的线程,并回调图片加载的cancel方法。

最后,我感兴趣的几个问题记录如上,有疑问,大家不吝赐教,可以一起探讨。

PS: 原文链接

上一篇 下一篇

猜你喜欢

热点阅读