Glide中的LruBitmapPool剖析

LruBitmapPool

LruBitmapPool為何而生呢?

摘抄自網(wǎng)上的一段解釋:
alvik和ART都沒(méi)有使用compacting garbage collector垃圾回收模式,這種模式中GC會(huì)遍歷堆,同時(shí)把活躍對(duì)象移到相鄰內(nèi)存區(qū)域,讓更大的內(nèi)存塊可以用在后續(xù)的分配中。因?yàn)榘沧繘](méi)有這種模式,就可能會(huì)出現(xiàn)被分配的對(duì)象分散在各處,對(duì)象之間只有很小的內(nèi)存可用。如果應(yīng)用試圖分配一個(gè)大于鄰近的閑置內(nèi)存塊空間的對(duì)象,就會(huì)導(dǎo)致OOM崩潰,即使總的空余內(nèi)存空間大于要分配的對(duì)象的大小。
而且,同步GC時(shí)會(huì)暫停所有線程(包括UI主線程)以便進(jìn)行GC,雖然暫停時(shí)間很短,但頻繁的同步GC會(huì)造成頁(yè)面卡頓,從而影響用戶體驗(yàn)。
因此為了避免頻繁的創(chuàng)建以及回收Bitmap對(duì)象,進(jìn)而減少GC的出現(xiàn),可以使用BitmapPool統(tǒng)一的管理Bitmap的創(chuàng)建以及重用。

使用LruBitmapPool后解決了些什么問(wèn)題呢?

因?yàn)镚lide提供了LruBitmapPool方法,從而使用圖片的加載進(jìn)一步高效化,從上面的解釋,簡(jiǎn)單概括就是避免Bitmap的頻繁創(chuàng)建,提高復(fù)用,減少了內(nèi)存抖動(dòng)

內(nèi)存抖動(dòng)是由于短時(shí)間內(nèi)有大量對(duì)象進(jìn)出Young Generiation區(qū)導(dǎo)致的,它伴隨著頻繁的GC。

LruBitmapPool源碼剖析

lrubitmappool.jpeg

從圖中大致可以了解到其LruBitmapPool調(diào)用流程(注意如果使用into(target)方法則不會(huì)使用LruBitmapPool機(jī)制),在位圖轉(zhuǎn)換的時(shí)候去查找LruBitmapPool中是否存在大小和配置信息相同的bitmap,有則返回

主要方法

put方法

@Override
  public synchronized void put(Bitmap bitmap) {
    if (bitmap == null) {
      throw new NullPointerException("Bitmap must not be null");
    }
    if (bitmap.isRecycled()) {
      throw new IllegalStateException("Cannot pool recycled bitmap");
    }
    if (!bitmap.isMutable() || strategy.getSize(bitmap) > maxSize
        || !allowedConfigs.contains(bitmap.getConfig())) {
      bitmap.recycle();
      return;
    }
    final int size = strategy.getSize(bitmap);
    strategy.put(bitmap);//存入LruPoolStrategy中
    tracker.add(bitmap);
    puts++;
    currentSize += size;
    dump();//輸出log信息
    evict();//根據(jù)currentSize計(jì)算是否超出maxSize,是則進(jìn)行末位回收
  }

get方法

傳入大小及配置信息來(lái)查找相匹配的位圖

  @Override
  @NonNull
  public Bitmap get(int width, int height, Bitmap.Config config) {
    Bitmap result = getDirtyOrNull(width, height, config);
    if (result != null) {
      result.eraseColor(Color.TRANSPARENT);//如果對(duì)象池存在位圖則擦拭該位圖像素
    } else {
      result = Bitmap.createBitmap(width, height, config);//創(chuàng)新新的位圖
    }
    return result;
  }

getDirtyOrNull方法

  @Nullable
  private synchronized Bitmap getDirtyOrNull(int width, int height, Bitmap.Config config) {
    assertNotHardwareConfig(config);
    final Bitmap result = strategy.get(width, height, config != null ? config : DEFAULT_CONFIG);
    if (result == null) {
      misses++;
    } else {
      hits++;
      currentSize -= strategy.getSize(result);
      tracker.remove(result);
      normalize(result);
    }
    dump();
    return result;
  }

在調(diào)用LruBitmapPool.get方法獲取到Bitmap后,通過(guò)如下方法將獲取到的bitmap作為參數(shù)傳給Canvas,在canvas中把inBitmap像素填充到進(jìn)去,通過(guò)對(duì)象復(fù)用,很好的優(yōu)化了內(nèi)存抖動(dòng)問(wèn)題


  private static void applyMatrix(@NonNull Bitmap inBitmap, @NonNull Bitmap targetBitmap,
      Matrix matrix) {
    BITMAP_DRAWABLE_LOCK.lock();
    try {
      Canvas canvas = new Canvas(targetBitmap);
      canvas.drawBitmap(inBitmap, matrix, DEFAULT_PAINT);
      clear(canvas);
    } finally {
      BITMAP_DRAWABLE_LOCK.unlock();
    }
  }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容