Fresco源码解析

作者: TheoT | 来源:发表于2018-03-07 11:37 被阅读0次

解码策略

5.0以上版本使用ArtDecoder,4.4以下使用GingerbreadPurgeableDecoder,4.4到5.0之间使用KitKatPurgeableDecoder。(GingerbreadPurgeableDecoder与KitKatPurgeableDecoder为DalvikPurgeableDecoder子类)

  public static PlatformDecoder buildPlatformDecoder(
      PoolFactory poolFactory,
      boolean directWebpDirectDecodingEnabled) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
      int maxNumThreads = poolFactory.getFlexByteArrayPoolMaxNumThreads();
      return new ArtDecoder(
          poolFactory.getBitmapPool(),
          maxNumThreads,
          new Pools.SynchronizedPool<>(maxNumThreads));
    } else {
      if (directWebpDirectDecodingEnabled
          && Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
        return new GingerbreadPurgeableDecoder();
      } else {
        return new KitKatPurgeableDecoder(poolFactory.getFlexByteArrayPool());
      }
    }
  }

内存简述

基本原理参照google BITMAP内存管理

以下为fresco内存池获取内存策略

public V get(int size) {
    ...
    //依据不同类型Bucket池获取Bucket大小
    int bucketedSize = getBucketedSize(size);
    int sizeInBytes = -1;
    synchronized (this) {
     //获取Bucket池中符合需要bucketSize的Bucket
      Bucket<V> bucket = getBucket(bucketedSize);
      if (bucket != null) {
        //从Bucket池中找到可以复用的内存返回使用
        V value = bucket.get();
        ...
        return value;
        }
        // fall through
      }
    ...
    V value = null;
    try {
      ...
      //如果Bucket池中不存在可复用的内存,则申请这段内存
      value = alloc(bucketedSize);
    }...
    ...
    return value;
  }
  • 5.0及以上系统使用ArtDecoder,利用系统inBitmap方式重用内存。
    KITKAT版本之后,只要创建的Bitmap总字节数大于需要的字节数,则可用于传递给inBitmap重用内存。

    解码流程

    protected CloseableReference<Bitmap> decodeStaticImageFromStream(
         InputStream inputStream, BitmapFactory.Options options, @Nullable Rect regionToDecode) {
       ...
       //从Bitmap内存池中获取可用Bitmap内存
       final Bitmap bitmapToReuse = mBitmapPool.get(sizeInBytes);
       ...
       options.inBitmap = bitmapToReuse;
       ...
       try {
        ...
        //解码流获取对应Bitmap存入设置到inBitmap的内存中
         if (decodedBitmap == null) {
           decodedBitmap = BitmapFactory.decodeStream(inputStream, null, options);
         }
       } ...
       return CloseableReference.of(decodedBitmap, mBitmapPool);
     }
    

    申请Bitmap内存空间方法

    @Override
    protected Bitmap alloc(int size) {
    return Bitmap.createBitmap(
        1,
        (int) Math.ceil(size / (double) BitmapUtil.RGB_565_BYTES_PER_PIXEL),
        Bitmap.Config.RGB_565);
    }
    
  • 5.0以下系统使用DalvikPurgeableDecoder,利用Option的inPurgeable参数,当inPurgeable为true,会将图片解码数据存放在Ashmem内存中。Ashmem在unpin之前,将不会被Android系统回收,在unpin之后,系统内存不足时,将会被系统回收。KitKatPurgeableDecoder与GingerbreadPurgeableDecoder最大的不同之处在于源编码数据的存放位置不同。

    GingerbreadPurgeableDecoder源数据存放于inPurgeable如下可以看到,当bitmap大于32K的时候,会将解码数据存放于ashmem中。

    BitmapFactory.cpp
    156  static SkPixelRef* installPixelRef(SkBitmap* bitmap, SkStream* stream,
    157                                   int sampleSize, bool ditherImage) {
    158    SkImageRef* pr;
    159    // only use ashmem for large images, since mmaps come at a price
    160    if (bitmap->getSize() >= 32 * 1024) {
    161        pr = new SkImageRef_ashmem(stream, bitmap->config(), sampleSize);
    162    } else {
    163        pr = new SkImageRef_GlobalPool(stream, bitmap->config(), sampleSize);
    164    }
    165    pr->setDitherImage(ditherImage);
    166    bitmap->setPixelRef(pr)->unref();
    167    pr->isOpaque(bitmap);
    168    return pr;
    169    }
            ...
    290    if (isPurgeable) {
    291        pr = installPixelRef(bitmap, stream, sampleSize, doDither);
    292    }
        
    

相关文章

  • Fresco源码解析

    解码策略 5.0以上版本使用ArtDecoder,4.4以下使用GingerbreadPurgeableDecod...

  • Fresco源码解析

    View 对应DraweeView类(实际上是DraweeHolder),其负责展示数据,显示图片。 Model对...

  • 源码解析

    OKHttp源码解析 Fresco图片框架内部实现原理探索 Android的Context Manager(服务管...

  • Fresco源码分析-Fresco初始化

    本文为分析Fresco源码第一篇,基于fresco 1.8.1。 Fresco官网对于Fresco设计的基本概述 ...

  • Fresco之webp源码解析

    前言 主流的Android的网络图片加载框架,各有利弊,目前公司项目都转用glide,并且把fresco从项目中移...

  • Fresco的源码学习

    前言 Fresco android图片加载的框架,facebook出品。 本文是对Fresco框架源码的阅读学习后...

  • Fresco图片显示原理浅析

    (第一篇)Fresco架构设计赏析 (第二篇)Fresco缓存架构分析 本文是Fresco源码分析系列第三篇文章,...

  • ios三方库解析

    YYCache 源码解析 YTKNetwork 源码解析 MJRefresh 源码解析 VVeboTableVie...

  • iOS 一些框架源码解析

    YYCache 源码解析 YTKNetwork源码解析 MJRefresh 源码解析 VVeboTableView...

  • Fresco缓存设计分析

    (第一篇)Fresco架构设计赏析 本文是Fresco源码分析系列第二篇文章,主要来看一下Fresco中有关图片缓...

网友评论

    本文标题:Fresco源码解析

    本文链接:https://www.haomeiwen.com/subject/cckjfftx.html