Android Fresco图片处理库用法API英文原文文档3(Facebook开源Android图片库)

这是英文文档的第三部分:IMAGE PIPELINE GUIDE

Introduction to the Image Pipeline

The image pipeline does everything necessary to get an image into a form where it can be rendered into an Android device.

The pipeline goes through the following steps when given an image to load:

  1. Look in the bitmap cache. If found, return it.
  2. Hand off to other threads.
  3. Check in the encoded memory cache. If found, decode, transform, and return it. Store in the bitmap cache.
  4. Check in the disk cache. If found, decode, transform, and return it. Store in the encoded-memory and bitmap caches.
  5. Check on the network (or other original source). If found, decode, transform, and return it. Store in all three caches.

This being an image library, an image is worth a thousand words:

(The ‘disk‘ cache as pictured includes the encoded memory cache, to keep the logic path clearer.) See this
page
 for more details on caching.

The pipeline can read from local files as well as network. PNG, GIF, and WebP are supported
as well as JPEG.

WebP on older platforms

WebP is often a useful image format, but Android did not support it at all until Android 3.0. Extended WebP format was not supported until Android 4.1.2.

The image pipeline transcodes unsupported WebP images into JPEG for you. This allows you to use WebP in your app all the way back to Android 2.3.

Configuring the Image Pipeline

Most apps can initialize Fresco completely by the simple command:

Fresco.initialize(context);

For those apps that need more advanced customization, we offer it using theImagePipelineConfig class.

Here is a maximal example. Rare is the app that actually needs all of these settings, but here they are for reference.

ImagePipelineConfig config = ImagePipelineConfig.newBuilder()
    .setBitmapMemoryCacheParamsSupplier(bitmapCacheParamsSupplier)
    .setCacheKeyFactory(cacheKeyFactory)
    .setEncodedMemoryCacheParamsSupplier(encodedCacheParamsSupplier)
    .setExecutorSupplier(executorSupplier)
    .setImageCacheStatsTracker(imageCacheStatsTracker)
    .setMainDiskCacheConfig(mainDiskCacheConfig)
    .setMemoryTrimmableRegistry(memoryTrimmableRegistry)
    .setNetworkFetchProducer(networkFetchProducer)
    .setPoolFactory(poolFactory)
    .setProgressiveJpegConfig(progressiveJpegConfig)
    .setRequestListeners(requestListeners)
    .setSmallImageDiskCacheConfig(smallImageDiskCacheConfig)
    .build();
Fresco.initialize(context, config);

Be sure to pass your ImagePipelineConfig object to Fresco.initialize! Otherwise, Fresco will use
a default configuration instead of the one you built.

Understanding Suppliers

Several of the configuration builder‘s methods take arguments of a Supplier of
an instance rather than an instance itself. This is a little more complex to create, but allows you to change behaviors while your app is running. Memory caches, for one, check their Supplier every five minutes.

If you don‘t need to dynamically change the params, use a Supplier that returns the same object each time:

Supplier<X> xSupplier = new Supplier<X>() {
  public X get() {
    return new X(xparam1, xparam2...);
  }
);
// when creating image pipeline
.setXSupplier(xSupplier);

Thread pools

By default, the image pipeline uses three thread pools:

  1. Three threads for network downloads
  2. Two threads for all disk operations - local file reads, and the disk cache
  3. Two threads for all CPU-bound operations - decodes, transforms, and background operations, such as postprocessing.

You can customize networking behavior by setting your own network layer.

To change the behavior for all other operations, pass in an instance of ExecutorSupplier.

Configuring the memory caches

The bitmap cache and the encoded memory cache are configured by a Supplier of aMemoryCacheParams object.

Configuring the disk cache

You use the builder pattern to create a DiskCacheConfig object:

DiskCacheConfig diskCacheConfig = DiskCacheConfig.newBuilder()
   .set....
   .set....
   .build()

// when building ImagePipelineConfig
.setMainDiskCacheConfig(diskCacheConfig)

Keeping cache stats#

If you want to keep track of metrics like the cache hit rate, you can implement theImageCacheStatsTracker class.
This provides callbacks for every cache event that you can use to keep your own statistics.

Caching

The three caches

1. Bitmap cache

The bitmap cache stores Android Bitmap objects. These are fully decoded images ready for display or postprocessing.

On Android 4.x and lower, the bitmap cache‘s data lives in the ashmem heap, not in the Java heap. This means that images don‘t force extra runs of the garbage collector, slowing down your app.

Android 5.0 has much improved memory management than earlier versions, so it is safer to leave the bitmap cache on the Java heap.

When your app is backgrounded, the bitmap cache is emptied.

2. Encoded memory cache

This cache stores images in their original compressed form. Images retrieved from this cache must be decoded before display.

If other transformations, such as resizing, rotating or transcoding were
requested, that happens before decode.

This cache is also emptied when your app is backgrounded.

3. Disk cache

(Yes, we know phones don‘t have disks, but it‘s too tedious to keep saying local storage cache...)

Like the encoded memory cache, this cache stores compressed image, which must be decoded and sometimes transformed before display.

Unlike the others, this cache is not cleared when your app is backgrounded, or if it exits, or even if the device is turned off. The user can, of course, always clear it from Android‘s Settings menu.

Using one disk cache or two?

Most apps need only a single disk cache. But in some circumstances you may want to keep smaller images in a separate cache, to prevent them from getting evicted too soon by larger images.

To do this, just call both setMainDiskCacheConfig and setSmallImageDiskCacheConfig methods when configuring
the image pipeline
.

What defines small? Your app does. When making an
image request
, you set its ImageType:

ImageRequest request = ImageRequest.newBuilderWithSourceUri(uri)
    .setImageType(ImageType.SMALL)

If you need only one cache, you can simply avoid calling setSmallImageDiskCacheConfig. The pipeline will default to using the same cache for both and ImageType will
be ignored.

Trimming the caches

When configuring the image pipeline, you can set the maximum size of each of the
caches. But there are times when you might want to go lower than that. For instance, your application might have caches for other kinds of data that might need more space and crowd out Fresco‘s. Or you might be checking to see if the device as a whole is running
out of storage space.

Fresco‘s caches implement the DiskTrimmable or MemoryTrimmable interfaces.
These are hooks into which your app can tell them to do emergency evictions.

Your application can then configure the pipeline with objects implementing theDiskTrimmableRegistry and MemoryTrimmableRegistry interfaces.

These objects must keep a list of trimmables. They must use app-specific logic to determine when memory or disk space must be preserved. They then notify the trimmable objects to carry out their trims.

Using the Image Pipeline Directly

This page is intended for advanced usage only. Most apps should be using Drawees to interact
with Fresco‘s image pipeline.

Using the image pipeline directly is challenging because of the memory usage. Drawees automatically keep track of whether or not your images need to be in memory. They will swap them out and load them back as soon as they need to be displayed. If you are using
the image pipeline directly, your app must repeat this logic.

The image pipeline returns objects wrapped in a CloseableReference. Drawees call the.close() method
on these objects when they are finished with them. If your app is not using Drawees, it must do the same.

The Java garbage collector will free image memory when Bitmap objects go out of scope, but this may be too late. Garbage collection is expensive, and relying on it for large objects leads to performance issues. This is especially true on Android 4.x and lower,
when Android did not maintain a separate memory space for Bitmaps.

Calling the pipeline

You must build an image request. Having done that, you can pass it directly to theImagePipeline:

ImagePipeline imagePipeline = Fresco.getImagePipeline();
DataSource<CloseableReference<CloseableImage>>
    dataSource = imagePipeline.fetchDecodedImage(imageRequest);

See the page on DataSources for information on how to receive data from them.

Skipping the decode

If you don‘t want to decode the image, but want to keep it in its original compressed format, just use fetchEncodedImage instead:

DataSource<CloseableReference<PooledByteBuffer>>
    dataSource = imagePipeline.fetchEncodedImage(imageRequest);

Instant results from the bitmap cache

Lookups to the bitmap cache, unlike the others, are done in the UI thread. If a Bitmap is there, you get it instantly.

DataSource<CloseableReference<CloseableImage>> dataSource =
    imagePipeline.fetchImageFromBitmapCache(imageRequest);
try {
  CloseableReference<CloseableImage> imageReference = dataSource.getResult();
  if (imageReference != null) {
    try {
      CloseableImage image = imageReference.get();
      // do something with the image
    } finally {
      CloseableReference.closeSafely(imageReference);
    }
  }
} finally {
  dataSource.close();
}

Do not skip this finally blocks!

Prefetching

Prefetching images in advance of showing them can sometimes lead to shorter wait times for users. Remember, however, that there are trade-offs. Prefetching takes up your users‘ data, and uses up its share of CPU and memory. As a rule, prefetching is not recommended
for most apps.

Nonetheless, the image pipeline allows you to prefetch to either disk or bitmap cache. Both will use more data for network URIs, but the disk cache will not do a decode and will therefore use less CPU.

Prefetch to disk:

imagePipeline.prefetchToDiskCache(imageRequest);

Prefetch to bitmap cache:

imagePipeline.prefetchToBitmapCache(imageRequest);

DataSources and DataSubscribers

DataSource is, like a Java Future,
the result of an asynchronous computation. The different is that, unlike a Future, a DataSource can return you a whole series of results from a single command, not just one.

After submitting an image request, the image pipeline returns a data source. To get a result out if it, you need to use a DataSubscriber.

I just want a bitmap...

If your request to the pipeline is for a decoded image - an Android Bitmap,
you can take advantage of our easier-to-use BaseBitmapDataSubscriber:

dataSource.subscribe(new BaseBitmapDataSubscriber() {
    @Override
    public void onNewResultImpl(@Nullable Bitmap bitmap) {
       // You can use the bitmap in only limited ways
      // No need to do any cleanup.
    }

    @Override
    public void onFailureImpl(DataSource dataSource) {
      // No cleanup required here.
    }
  });

A snap to use, right? There is a caveat.

You can not assign the bitmap to any variable not in the scope of the onNewResultImplmethod. The reason is that, after the subscriber
has finished executing, the image pipeline will recycle the bitmap and free its memory. If you try to draw the bitmap after that, your app will crash with an IllegalStateException.

General-purpose solution

If you want to keep the bitmap around, you can‘t use raw Bitmaps at all. You must make use of closeable
references
 and the BaseDataSubscriber:

DataSubscriber dataSubscriber =
    new BaseDataSubscriber<CloseableReference<CloseableImage>>() {
  @Override
  public void onNewResultImpl(
      DataSource<CloseableReference<CloseableImage>> dataSource) {

    if (!dataSource.isFinished()) {
      FLog.v("Not yet finished - this is just another progressive scan.");
    }  

    CloseableReference<CloseableImage> imageReference = dataSource.getResult();
    if (imageReference != null) {
      try {
        CloseableImage image = imageReference.get();
        // do something with the image
      } finally {
        imageReference.close();
      }
    }
  }
  @Override
  public void onFailureImpl(DataSource dataSource) {
    Throwable throwable = dataSource.getFailureCause();
    // handle failure
  }
};

dataSource.subscribe(dataSubscriber, executor);

If you want to deviate from the example above and assign the CloseableReference to another variable somewhere else, you can. Just be sure to follow
the rules
.

Closeable References

This page is intended for advanced usage only.

Most apps should use Drawees and not worry about closing.

The Java language is garbage-collected and most developers are used to creating objects willy-nilly and taking it for granted they will eventually disappear from memory.

Until Android 5.0‘s improvements, this was not at all a good idea for Bitmaps. They take up a large share of the memory of a mobile device. Their existence in memory would make the garbage collector run more frequently, making image-heavy apps slow and janky.

Bitmaps were the one thing that makes Java developers miss C++ and its many smart pointer libraries, such as Boost.

Fresco‘s solution is found in the CloseableReference class.
In order to use it correctly, you must follow the rules below:

1. The caller owns the reference.

Here, we create a reference, but since we‘re passing it to a caller, the caller takes it:

CloseableReference<Val> foo() {
  Val val;
  return CloseableReference.of(val);
}

2. The owner must close the reference before leaving scope.

Here we create a reference, but are not passing it to a caller. So we must close it:

void gee() {
  CloseableReference<Val> ref = foo();
  try {
    haa(ref);
  } finally {
    ref.close();
  }
}

The finally block is almost always the best way to do this.

3. Something other than the owner should not close the reference.

Here, we are receiving the reference via argument. The caller is still the owner, so we are not supposed to close it.

void haa(CloseableReference<?> ref) {
  Log.println("Haa: " + ref.get());
}

If we called .close() here by mistake, then if the caller tried to call .get(), anIllegalStateException would
be thrown.

4. Always clone the reference before assigning.

If we need to hold onto the reference, we need to clone it.

If using it in a class:

class MyClass {
  CloseableReference<Val> myValRef;

  void mmm(CloseableReference<Val> ref) {
    myValRef = ref.clone();
  };
  // caller can now safely close its copy as we made our own clone.

  void close() {
    CloseableReference.closeSafely(myValRef);
  }
}
// Now the caller of MyClass must close it!

If using it in an inner class:

void haa(CloseableReference<?> ref) {
  final CloseableReference<?> refClone = ref.clone();
  executor.submit(new Runnable() {
    public void run() {
      try {
        Log.println("Haa Async: " + refClone.get());
      } finally {
        refClone.close();
      }
    }
  });
  // caller can now safely close its copy as we made our own clone.
}
时间: 2024-10-12 09:40:14

Android Fresco图片处理库用法API英文原文文档3(Facebook开源Android图片库)的相关文章

Android Fresco图片处理库用法API英文原文文档2-2(Facebook开源Android图片库)

Android Fresco图片处理库用法API英文原文文档2-2(Facebook开源Android图片库) 这是英文文档的第二部分(2):DRAWEE GUIDE 由于第二部分内容多一些,所以分为2个文章发.方便大家查看. Using the ControllerBuilder SimpleDraweeView has two methods for specifying an image. The easy way is to just callsetImageURI. If you wa

Android Fresco图片处理库用法API英文原文文档1(Facebook开源Android图片库)

Fresco是Facebook最新推出的一款用于Android应用中展示图片的强大图片库,可以从网络.本地存储和本地资源中加载图片.其中的Drawees可以显示占位符,直到图片加载完成.而当图片从屏幕上消失时,会自动释放内存. 功能很强大,为了大家学习方便,我将英文原文文档给大家迁移过来,供参考学习. 这是英文文档的第一部分:QUICK START QUICK START Adding Fresco to your Project Here's how to add Fresco to your

Android Fresco图片处理库用法API英文原文文档4(Facebook开源Android图片库)

这是英文文档的第三部分:THIRD PARTY LIBRARIES Using Other Network Layers By default, the image pipeline uses the HttpURLConnection networking library bundled with Android. Apps may have their own network layer they may wish to use instead. Using OkHttp OkHttp is

Android Fresco图片处理库用法API英文原文文档2-1(Facebook开源Android图片库)

这是英文文档的第二部分(1):DRAWEE GUIDE 由于第二部分内容多一些,所以分为2个文章发.方便大家查看. Using Drawees in XML Drawees have very extensive customization facilities. The best way to customize your Drawee is to do so in the XML. Here is an example that sets nearly all possible option

Android 一起来看看知乎开源的图片选择库

前言 在实际开发中,图片选择器一直都是必不可少的一个部分,不管是 QQ 头像的设置,还是发送一条装逼的微信朋友圈,都要用到图片选择器来给用户选择他们想要上传的图片,最近知乎开源了一款图片选择库 Matisse 简直美哭了,而且完全遵循 Android 交互设计规范,实在是很良心. 在开始正文之前,先欣赏一下这个图片选择器的效果 是不是感觉相当的简洁好看,反正我是这么认为的. 一.基本使用 1.导入相应的依赖库 Gradle: repositories { jcenter() } dependen

Android 解决图片大量下载:软引用必须懂4点

Android 解决图片大量下载:软引用必须懂4点 可能对于Android开发者来说,软引用这个词有的会不是很熟悉,软引用在Java开发中用的比较多,但是,在Android开发中引用软引用,会给我们解决很多难题. AD: 1.对象的强.软.弱和虚引用 为了能更加灵活控制对象的生命周期,需要知道对象引用的4中级别,由高到低依次为 :强引用.软引用.弱引用和虚引用 备注: 这四种的区别: ⑴强引用(StrongReference) 强引用是使用最普遍的引用.如果一个对象具有强引用,那垃圾回收器绝不会

Universal-Image-Loader,android-Volley,Picasso、Fresco和Glide图片缓存库的联系与区别

Universal-Image-Loader,android-Volley,Picasso.Fresco和Glide五大Android开源组件加载网络图片比较 在Android中的加载网络图片是一件十分令人头疼的事情,在网上有着许多关于加载网络图片的开源库,可以让我们十分方便的加载网络图片.在这里介绍一下Universal-Image-Loader,android-Volley,Picasso.Fresco和Glide的一些使用以及最基本的用法介绍. 1. // imageView是一个Imag

Android图片剪裁库

最近利用一周左右的业余时间,终于完成了一个Android图片剪裁库,核心功能是根据自己的理解实现的,部分代码参考了Android源码的图片剪裁应用.现在将该代码开源在Github上以供大家学习和使用,地址:https://github.com/Jhuster/ImageCropper,效果如下所示: 我的大致计划是首先介绍一下这个库的用法,然后再写几篇文章介绍一下其中的一些原理和关键技术,希望对Android开发新手有所帮助. [特性] 支持通过手势移动和缩放剪裁窗口 支持固定剪裁窗口大小.固定

Android压缩图片和libjpeg库

前言 Fjpeg使用 Fjpeg 注意 如何使用 如何压缩图片只改变在硬盘的存储大小 如何改变图片分辨率让其Bitmap对象可以加载到内存中 关于重载版本 开始学习之旅 补充知识的结论 修改图片分辨率 防止在Android加载Bitmap的时候oom内存溢出 解决方案1 解决方案2 希望压缩图片方便网络传输 第一种方案利用Bitmapcompress方法压缩 第二种利用libjpeg压缩 在Android50测试两个 图片压缩 在Android60测试两个 图片压缩 解释Android50和60