private void updateImageRequests() {
    if (!mIsActive) return;

    int currentIndex = mCurrentIndex;
    MediaItem item = mData[currentIndex % DATA_CACHE_SIZE];
    if (item == null || item.getPath() != mItemPath) {
      // current item mismatch - don't request image
      return;
    }

    // 1. Find the most wanted request and start it (if not already started).
    Future<?> task = null;
    for (int i = 0; i < sImageFetchSeq.length; i++) {
      int offset = sImageFetchSeq[i].indexOffset;
      int bit = sImageFetchSeq[i].imageBit;
      task = startTaskIfNeeded(currentIndex + offset, bit);
      if (task != null) break;
    }

    // 2. Cancel everything else.
    for (ImageEntry entry : mImageCache.values()) {
      if (entry.screenNailTask != null && entry.screenNailTask != task) {
        entry.screenNailTask.cancel();
        entry.screenNailTask = null;
        entry.requestedBits &= ~BIT_SCREEN_NAIL;
      }
      if (entry.fullImageTask != null && entry.fullImageTask != task) {
        entry.fullImageTask.cancel();
        entry.fullImageTask = null;
        entry.requestedBits &= ~BIT_FULL_IMAGE;
      }
    }
  }
  // Returns the task if we started the task or the task is already started.
  private Future<?> startTaskIfNeeded(int index, int which) {
    if (index < mActiveStart || index >= mActiveEnd) return null;

    ImageEntry entry = mImageCache.get(getVersion(index));
    if (entry == null) return null;

    if (which == BIT_SCREEN_NAIL && entry.screenNailTask != null) {
      return entry.screenNailTask;
    } else if (which == BIT_FULL_IMAGE && entry.fullImageTask != null) {
      return entry.fullImageTask;
    }

    MediaItem item = mData[index % DATA_CACHE_SIZE];
    Utils.assertTrue(item != null);

    if (which == BIT_SCREEN_NAIL && (entry.requestedBits & BIT_SCREEN_NAIL) == 0) {
      entry.requestedBits |= BIT_SCREEN_NAIL;
      entry.screenNailTask =
          mThreadPool.submit(
              new ScreenNailJob(item), new ScreenNailListener(item.getDataVersion()));
      // request screen nail
      return entry.screenNailTask;
    }
    if (which == BIT_FULL_IMAGE
        && (entry.requestedBits & BIT_FULL_IMAGE) == 0
        && (item.getSupportedOperations() & MediaItem.SUPPORT_FULL_IMAGE) != 0) {
      entry.requestedBits |= BIT_FULL_IMAGE;
      entry.fullImageTask =
          mThreadPool.submit(
              item.requestLargeImage(), new FullImageListener(item.getDataVersion()));
      // request full image
      return entry.fullImageTask;
    }
    return null;
  }
  private void updateScreenNail(long version, Future<Bitmap> future) {
    ImageEntry entry = mImageCache.get(version);
    if (entry == null || entry.screenNailTask != future) {
      Bitmap screenNail = future.get();
      if (screenNail != null) screenNail.recycle();
      return;
    }

    entry.screenNailTask = null;
    entry.screenNail = future.get();

    if (entry.screenNail == null) {
      entry.failToLoad = true;
      /*a@nufront start*/
      for (int i = -1; i <= 1; ++i) {
        if (version == getVersion(mCurrentIndex + i)) {
          if (0 == i) updateTileProvider(entry);
          mPhotoView.notifyImageInvalidated(i);
        }
      }
      /*a@nufront end*/
    } else {
      if (mDataListener != null) {
        mDataListener.onPhotoAvailable(version, false);
      }
      for (int i = -1; i <= 1; ++i) {
        if (version == getVersion(mCurrentIndex + i)) {
          if (i == 0) updateTileProvider(entry);
          mPhotoView.notifyImageInvalidated(i);
        }
      }
    }
    updateImageRequests();
  }