Native API 之 ImageLoader

在Android端,React Native采用了Fresco图片库来进行图片相关的操作,因此RN所有的图片管理策略都基于Fresco。
ImageLoaderModule利用Fresco向JS端提供了图片加载相关的能力,该module主要API方法如下:

  • getSize 获取网络图片的宽高
  • prefetchImage 预加载图片到磁盘缓存
  • abortRequest 取消请求任务
  • queryCache 根据uri查询该图片的缓存位置(memory 或者 disk)

具体实现分析如下。


getSize

  • input: 图片的URI
  • output:图片尺寸对象
{
    “width”:400,
    "height":300
}

getSize 异步获取网络图片的宽高:

  public void getSize(
      final String uriString,
      final Promise promise) {
    if (uriString == null || uriString.isEmpty()) {
      promise.reject(ERROR_INVALID_URI, "Cannot get the size of an image for an empty URI");
      return;
    }

    Uri uri = Uri.parse(uriString);
    // 根据URI 创建图片请求对象
    ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri).build();
    // 下载图片并decode
    DataSource> dataSource =
      Fresco.getImagePipeline().fetchDecodedImage(request, mCallerContext);

    DataSubscriber> dataSubscriber =
      new BaseDataSubscriber>() {
        @Override
        protected void onNewResultImpl(
            DataSource> dataSource) {
          if (!dataSource.isFinished()) {
            return;
          }
          CloseableReference ref = dataSource.getResult();
          if (ref != null) {
            try {
              CloseableImage image = ref.get();

              WritableMap sizes = Arguments.createMap();
              sizes.putInt("width", image.getWidth());
              sizes.putInt("height", image.getHeight());

              promise.resolve(sizes);
            } catch (Exception e) {
              promise.reject(ERROR_GET_SIZE_FAILURE, e);
            } finally {
              CloseableReference.closeSafely(ref);
            }
          } else {
            promise.reject(ERROR_GET_SIZE_FAILURE);
          }
        }

        @Override
        protected void onFailureImpl(DataSource> dataSource) {
          promise.reject(ERROR_GET_SIZE_FAILURE, dataSource.getFailureCause());
        }
      };
    dataSource.subscribe(dataSubscriber, CallerThreadExecutor.getInstance());
  }

prefetchImage

  • input:图片的URI,标识请求的ID
  • output:图片是否预加载成功

prefetchImage 将图片下载到磁盘缓存中

  public void prefetchImage(
    final String uriString,
    final int requestId,
    final Promise promise)
  {
    if (uriString == null || uriString.isEmpty()) {
      promise.reject(ERROR_INVALID_URI, "Cannot prefetch an image for an empty URI");
      return;
    }

    Uri uri = Uri.parse(uriString);
    ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri).build();
    //下载图片到磁盘
    DataSource prefetchSource =
      Fresco.getImagePipeline().prefetchToDiskCache(request, mCallerContext);
    DataSubscriber prefetchSubscriber = new BaseDataSubscriber() {
      @Override
      protected void onNewResultImpl(DataSource dataSource) {
        if (!dataSource.isFinished()) {
          return;
        }
        try {
          removeRequest(requestId);
          promise.resolve(true);
        } finally {
          dataSource.close();
        }
      }

      @Override
      protected void onFailureImpl(DataSource dataSource) {
        try {
          removeRequest(requestId);
          promise.reject(ERROR_PREFETCH_FAILURE, dataSource.getFailureCause());
        } finally {
          dataSource.close();
        }
      }
    };
    registerRequest(requestId, prefetchSource);
    prefetchSource.subscribe(prefetchSubscriber, CallerThreadExecutor.getInstance());
  }

queryCache
input: 待查询的uri 数组
output: 图片位于缓存的位置对象

{ 
    "https://s.geilicdn.com/CPC/common/201705/header/images/logo-5f5aeedef4.png": "disk", 
    "https://s.geilicdn.com/CPC/loginNew/201706/login/images/topic-bb6756e79d.png": "memory"
}

根据uri查询异步图片所在缓存类型:

public void queryCache(final ReadableArray uris, final Promise promise) {
    // perform cache interrogation in async task as disk cache checks are expensive
    new GuardedAsyncTask(getReactApplicationContext()) {
      @Override
      protected void doInBackgroundGuarded(Void... params) {
        WritableMap result = Arguments.createMap();
        ImagePipeline imagePipeline = Fresco.getImagePipeline();
        for (int i = 0; i < uris.size(); i++) {
          String uriString = uris.getString(i);
          final Uri uri = Uri.parse(uriString);
          if (imagePipeline.isInBitmapMemoryCache(uri)) {
            result.putString(uriString, "memory");
          } else if (imagePipeline.isInDiskCacheSync(uri)) {
            result.putString(uriString, "disk");
          }
        }
        promise.resolve(result);
      }
    }.executeOnExecutor(GuardedAsyncTask.THREAD_POOL_EXECUTOR);
  }

你可能感兴趣的:(Native API 之 ImageLoader)