源碼分析之Fresco(1)

com.facebook.imagepipeline.core/ImagePipeline.java

 
[1]取圖片從BitmapCache
>public DataSource<CloseableReference<CloseableImage>> fetchImageFromBitmapCache( ImageRequest imageRequest, Object callerContext)
>> submitFetchRequest() 
>>>CloseableProducerToDataSourceAdapter.create()生產(chǎn)者到數(shù)據(jù)源的一個(gè)適配器

該適配器目錄com.facebook.imagepipeline.datasource/CloseableProducerToDataSourceAdapter.java

@看看定義
CloseableProducerToDataSourceAdapter<T> extends AbstractProducerToDataSourceAdapter<CloseableReference<T>>

@跟蹤create方法
create()---> super(producer, settableProducerContext, listener)父類的構(gòu)造方法
           >>producer.produceResults(createConsumer(), settableProducerContext)
執(zhí)行父類構(gòu)造方法瞒瘸,父類開(kāi)始 告訴 生成者 開(kāi)始生產(chǎn)作業(yè)了produceResults();


@那么這個(gè)producer生產(chǎn)者是誰(shuí)呢?
:::::: producerSequence這玩意
>  Producer<CloseableReference<CloseableImage>> producerSequence =
                    mProducerSequenceFactory.getDecodedImageProducerSequence(imageRequest);
                                                         ^
@mProducerSequenceFactory工廠產(chǎn)生生產(chǎn)者
                                                         ^
   public Producer<CloseableReference<CloseableImage>> getDecodedImageProducerSequence(ImageRequest imageRequest) {
        Producer<CloseableReference<CloseableImage>> pipelineSequence =
                getBasicDecodedImageSequence(imageRequest);
        if (imageRequest.getPostprocessor() != null) {
            return getPostprocessorSequence(pipelineSequence);
        } else {
            return pipelineSequence;
        }
    }
@看看pipelineSequence怎么得來(lái):

private Producer<CloseableReference<CloseableImage>> getBasicDecodedImageSequence(ImageRequest imageRequest) {
        Preconditions.checkNotNull(imageRequest);//判空

        Uri uri = imageRequest.getSourceUri();//圖片地址
        Preconditions.checkNotNull(uri, "Uri is null.");//判空
        if (UriUtil.isNetworkUri(uri)) {//網(wǎng)絡(luò)地址
            return getNetworkFetchSequence();
        } else if (UriUtil.isLocalFileUri(uri)) {//本地文件地址
            if (MediaUtils.isVideo(MediaUtils.extractMime(uri.getPath()))) {
                return getLocalVideoFileFetchSequence();
            } else {
                return getLocalImageFileFetchSequence();
            }
        } else if (UriUtil.isLocalContentUri(uri)) {//content地址 如 content://sms/inbox
            return getLocalContentUriFetchSequence();
        } else if (UriUtil.isLocalAssetUri(uri)) {//本地Asset地址
            return getLocalAssetFetchSequence();
        } else if (UriUtil.isLocalResourceUri(uri)) {//本地Resource地址
            return getLocalResourceFetchSequence();
        } else if (UriUtil.isDataUri(uri)) {
            return getDataFetchSequence();
        } else {
            String uriString = uri.toString();
            if (uriString.length() > 30) {
                uriString = uriString.substring(0, 30) + "...";
            }
            throw new RuntimeException("Unsupported uri scheme! Uri is: " + uriString);
        }
    }

根據(jù)uri類型 來(lái)返回 不同的 Producer生產(chǎn)者.

@繼續(xù)跟代碼
1、如果是網(wǎng)絡(luò)地址 getNetworkFetchSequence();
                  > mNetworkFetchSequence = newBitmapCacheGetToDecodeSequence(getCommonNetworkFetchToEncodedMemorySequence());
                                                 
                  >>
    private Producer<CloseableReference<CloseableImage>> newBitmapCacheGetToDecodeSequence(Producer<EncodedImage> inputProducer) {
        DecodeProducer decodeProducer = mProducerFactory.newDecodeProducer(inputProducer);
        return newBitmapCacheGetToBitmapCacheSequence(decodeProducer);
    }

    com.facebook.imagepipeline.core/ProducerFactory.java
    先是 調(diào)用工廠類 ProducerFactory.newDecodeProducer得到一個(gè)DecodeProducer解碼生產(chǎn)者

    

   newBitmapCacheGetToBitmapCacheSequence(inputProducer)做了啥?
   :ProducerFactory生了BitmapMemoryCacheProducer久免,進(jìn)化成BitmapMemoryCacheKeyMultiplexProducer颁井,再次進(jìn)化ThreadHandoffProducer【這貨后面有用到】
   然并卵 
   return mProducerFactory.newBitmapMemoryCacheGetProducer(threadHandoffProducer);
   >                              ||
          public BitmapMemoryCacheGetProducer newBitmapMemoryCacheGetProducer(
                Producer<CloseableReference<CloseableImage>> inputProducer) {
                 return new BitmapMemoryCacheGetProducer(mBitmapMemoryCache, mCacheKeyFactory, inputProducer);
           }

   最后超級(jí)進(jìn)化成 @BitmapMemoryCacheGetProducer

   @2大工廠 @ProducerSequenceFactory 和 @ProducerFactory  前面又字面意思可以理解 一系列工廠翅敌,肯定是總廠音诈,下面很多分廠;

   回到主線 producer.produceResults(createConsumer(), settableProducerContext); 找到了 生產(chǎn)者就要開(kāi)始生產(chǎn)了P逭拧4鹩妗!
   主角是 BitmapMemoryCacheGetProducer 官方注釋是 只讀的生產(chǎn)者,暫時(shí)有點(diǎn)懵逼
   主角父親是BitmapMemoryCacheProducer這貨

   @Override
    public void produceResults(final Consumer<CloseableReference<CloseableImage>> consumer, final ProducerContext producerContext) {

        final ProducerListener listener = producerContext.getListener();
        final String requestId = producerContext.getId();
        listener.onProducerStart(requestId, getProducerName());//告訴listener開(kāi)始生產(chǎn)
        final ImageRequest imageRequest = producerContext.getImageRequest();

        final CacheKey cacheKey = mCacheKeyFactory.getBitmapCacheKey(imageRequest);//先取緩存鑰匙
        CloseableReference<CloseableImage> cachedReference = mMemoryCache.get(cacheKey);//取圖片

        if (cachedReference != null) {//緩存存在
            boolean isFinal = cachedReference.get().getQualityInfo().isOfFullQuality();
            if (isFinal) {
                listener.onProducerFinishWithSuccess(
                        requestId,
                        getProducerName(),
                        listener.requiresExtraMap(requestId) ? ImmutableMap.of(VALUE_FOUND, "true") : null);
                consumer.onProgressUpdate(1f);//進(jìn)度報(bào)告 完美
            }
            consumer.onNewResult(cachedReference, isFinal);//消費(fèi)者 得到 產(chǎn)品
            cachedReference.close();
            if (isFinal) {
                return;
            }
        }

        if (producerContext.getLowestPermittedRequestLevel().getValue() >=
                ImageRequest.RequestLevel.BITMAP_MEMORY_CACHE.getValue()) {//最低請(qǐng)求等級(jí)判斷 ,BITMAP_MEMORY_CACHE是最高等級(jí)
            listener.onProducerFinishWithSuccess(
                    requestId,
                    getProducerName(),
                    listener.requiresExtraMap(requestId) ? ImmutableMap.of(VALUE_FOUND, "false") : null);
            consumer.onNewResult(null, true);
            return;
        }
        //包裝消費(fèi)者
        Consumer<CloseableReference<CloseableImage>> wrappedConsumer = wrapConsumer(consumer, cacheKey);
        listener.onProducerFinishWithSuccess(requestId,
                getProducerName(),
                listener.requiresExtraMap(requestId) ? ImmutableMap.of(VALUE_FOUND, "false") : null);
        mInputProducer.produceResults(wrappedConsumer, producerContext);//再次生產(chǎn)
    }
   
    @RequestLevel.java  是com.facebook.imagepipeline.request.ImageRequest的內(nèi)部類
    
    /* Fetch (from the network or local storage) */
    FULL_FETCH(1),
    /* Disk caching */
    DISK_CACHE(2),
    /* Encoded memory caching */
    ENCODED_MEMORY_CACHE(3),
    /* Bitmap caching */
    BITMAP_MEMORY_CACHE(4);

      
    mInputProducer是誰(shuí)呢? 另一個(gè)生產(chǎn)者閃亮登場(chǎng)了 ThreadHandoffProducer 這貨
    這貨是 怎么 產(chǎn)生的?
    ThreadHandoffProducer<CloseableReference<CloseableImage>> threadHandoffProducer =
                mProducerFactory.newBackgroundThreadHandoffProducer(bitmapKeyMultiplexProducer, mThreadHandoffProducerQueue);
    還是離不開(kāi)ProducerFactory工廠類
    參數(shù)2:mThreadHandoffProducerQueue 侥涵,它里面 有一個(gè)Executor 線程執(zhí)行器 和 ArrayList<Runnable>容器沼撕;
    其實(shí) 就是 一個(gè) 線程池吧。
    //ThreadHandoffProducer開(kāi)始生產(chǎn)
    @Override
    public void produceResults(final Consumer<T> consumer, final ProducerContext context) {
        final ProducerListener producerListener = context.getListener();
        final String requestId = context.getId();
        final StatefulProducerRunnable<T> statefulRunnable = new StatefulProducerRunnable<T>(
                consumer, producerListener, PRODUCER_NAME, requestId) {
            @Override
            protected void onSuccess(T ignored) {
                producerListener.onProducerFinishWithSuccess(requestId, PRODUCER_NAME, null);
                mInputProducer.produceResults(consumer, context);//關(guān)鍵是 這句代碼
            }

            @Override
            protected void disposeResult(T ignored) {
            }

            @Override
            protected T getResult() throws Exception {
                return null;
            }
        };
        context.addCallbacks(new BaseProducerContextCallbacks() {
                    @Override
                    public void onCancellationRequested() {
                        statefulRunnable.cancel();
                        mThreadHandoffProducerQueue.remove(statefulRunnable);
                    }
                });
        mThreadHandoffProducerQueue.addToQueueOrExecute(statefulRunnable); //丟到線程池 執(zhí)行
    }
    
    
    在 onSuccess()回調(diào)方法里 ThreadHandoffProducer的mInputProducer開(kāi)始 登場(chǎng)芜飘,
    此mInputProducer引用的對(duì)象是 BitmapMemoryCacheKeyMultiplexProducer bitmapKeyMultiplexProducer =
                mProducerFactory.newBitmapMemoryCacheKeyMultiplexProducer(bitmapMemoryCacheProducer);
    順藤摸瓜 跟到BitmapMemoryCacheKeyMultiplexProducer的父類 MultiplexProducer
    >produceResults()
    >>startInputProducerIfHasAttachedConsumers()
    >>>mInputProducer.produceResults(forwardingConsumer, multiplexProducerContext);
    最后 又把任務(wù)交給 另一個(gè)生產(chǎn)者mInputProducer
    BitmapMemoryCacheProducer bitmapMemoryCacheProducer =
                mProducerFactory.newBitmapMemoryCacheProducer(inputProducer);
    看看 BitmapMemoryCacheProducer 的 
        @Override
    public void produceResults(final Consumer<CloseableReference<CloseableImage>> consumer,
            final ProducerContext producerContext) {
        ......
        Consumer<CloseableReference<CloseableImage>> wrappedConsumer = wrapConsumer(consumer, cacheKey);
        listener.onProducerFinishWithSuccess(
                requestId,
                getProducerName(),
                listener.requiresExtraMap(requestId) ? ImmutableMap.of(VALUE_FOUND, "false") : null);
        mInputProducer.produceResults(wrappedConsumer, producerContext);
    }
    哭笑不得 又交給 另一個(gè)生產(chǎn)者mInputProducer
    只能往回看代碼了 :
    DecodeProducer decodeProducer = mProducerFactory.newDecodeProducer(inputProducer);
    解碼生產(chǎn)者 
    @Override
    public void produceResults(final Consumer<CloseableReference<CloseableImage>> consumer,
            final ProducerContext producerContext) {
        final ImageRequest imageRequest = producerContext.getImageRequest();
        ProgressiveDecoder progressiveDecoder;
        if (!UriUtil.isNetworkUri(imageRequest.getSourceUri())) {//不是網(wǎng)絡(luò)地址
            progressiveDecoder = new LocalImagesProgressiveDecoder(consumer, producerContext);
        } else { //是網(wǎng)絡(luò)圖片地址
            ProgressiveJpegParser jpegParser = new ProgressiveJpegParser(mByteArrayPool);
            progressiveDecoder = new NetworkImagesProgressiveDecoder(consumer,
                    producerContext,
                    jpegParser,
                    mProgressiveJpegConfig);
        }
        mInputProducer.produceResults(progressiveDecoder, producerContext);
    }

    繼續(xù)跟 這個(gè) mInputProducer,找源頭吧 
    private synchronized Producer<CloseableReference<CloseableImage>> getNetworkFetchSequence() {
        if (mNetworkFetchSequence == null) {
            mNetworkFetchSequence = newBitmapCacheGetToDecodeSequence(getCommonNetworkFetchToEncodedMemorySequence());
        }
        return mNetworkFetchSequence;
    }
    到這里 getCommonNetworkFetchToEncodedMemorySequence()返回生產(chǎn)者

     /**
     * multiplex -> encoded cache -> disk cache -> (webp transcode) -> network fetch.
     */
    private synchronized Producer<EncodedImage> getCommonNetworkFetchToEncodedMemorySequence() {
        if (mCommonNetworkFetchToEncodedMemorySequence == null) {
            Producer<EncodedImage> inputProducer = newEncodedCacheMultiplexToTranscodeSequence(
                            mProducerFactory.newNetworkFetchProducer(mNetworkFetcher)); //這里是生存者 源頭 
            mCommonNetworkFetchToEncodedMemorySequence =
                    ProducerFactory.newAddImageTransformMetaDataProducer(inputProducer);

            if (mResizeAndRotateEnabledForNetwork && !mDownsampleEnabled) { //需要調(diào)整大小 和 旋轉(zhuǎn) 
                mCommonNetworkFetchToEncodedMemorySequence = mProducerFactory.newResizeAndRotateProducer(
                                mCommonNetworkFetchToEncodedMemorySequence);
            }
        }
        return mCommonNetworkFetchToEncodedMemorySequence;
    }

    直接看源頭NetworkFetchProducer 網(wǎng)絡(luò)獲取生產(chǎn)者(從網(wǎng)絡(luò)獲取圖片唄)
      @Override
  public void produceResults(Consumer<EncodedImage> consumer, ProducerContext context) {
    context.getListener()
            .onProducerStart(context.getId(), PRODUCER_NAME);
    final FetchState fetchState = mNetworkFetcher.createFetchState(consumer, context);
    mNetworkFetcher.fetch(fetchState, new NetworkFetcher.Callback() {
              @Override
              public void onResponse(InputStream response, int responseLength) throws IOException {
                NetworkFetchProducer.this.onResponse(fetchState, response, responseLength);
              }

              @Override
              public void onFailure(Throwable throwable) {
                NetworkFetchProducer.this.onFailure(fetchState, throwable);
              }

              @Override
              public void onCancellation() {
                NetworkFetchProducer.this.onCancellation(fetchState);
              }
            });
  }

  mNetworkFetcher是 由 ImagePipelineConfig 初始化的 時(shí)候配置的 
  mNetworkFetcher = builder.mNetworkFetcher == null ?
            new HttpUrlConnectionNetworkFetcher() : builder.mNetworkFetcher;
  默認(rèn)配置下ImagePipelineConfig.Builder類的 mNetworkFetcher為 null务豺;
  mNetworkFetcher 指向的 就是  HttpUrlConnectionNetworkFetcher,F(xiàn)resco默認(rèn)的網(wǎng)絡(luò)連接用的是HttpUrlConnection;
  HttpUrlConnectionNetworkFetcher的 fetch() 方法里
  @Override
    public void fetch(final FetchState fetchState, final Callback callback) {
        final Future<?> future = mExecutorService.submit(new Runnable() {
                    @Override
                    public void run() {
                        fetchSync(fetchState, callback);
                    }
                });//開(kāi)了個(gè)線程執(zhí)行下載圖片操作
         ......
    }
   
   void fetchSync(FetchState fetchState, Callback callback) {
        HttpURLConnection connection = null;
        try {
            connection = downloadFrom(fetchState.getUri(), MAX_REDIRECTS);//終于要下載了
            if (connection != null) {
                callback.onResponse(connection.getInputStream(), -1);
            }
        } catch (IOException e) {
            callback.onFailure(e);
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }

    }
以上是網(wǎng)絡(luò)加載圖片步驟...
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末燃箭,一起剝皮案震驚了整個(gè)濱河市冲呢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌招狸,老刑警劉巖敬拓,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異裙戏,居然都是意外死亡乘凸,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén)累榜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)营勤,“玉大人,你說(shuō)我怎么就攤上這事壹罚「鹱鳎” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵猖凛,是天一觀的道長(zhǎng)赂蠢。 經(jīng)常有香客問(wèn)我,道長(zhǎng)辨泳,這世上最難降的妖魔是什么虱岂? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任玖院,我火速辦了婚禮,結(jié)果婚禮上第岖,老公的妹妹穿的比我還像新娘难菌。我一直安慰自己,他們只是感情好蔑滓,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布郊酒。 她就那樣靜靜地躺著,像睡著了一般烫饼。 火紅的嫁衣襯著肌膚如雪猎塞。 梳的紋絲不亂的頭發(fā)上试读,一...
    開(kāi)封第一講書(shū)人閱讀 49,741評(píng)論 1 289
  • 那天杠纵,我揣著相機(jī)與錄音,去河邊找鬼钩骇。 笑死比藻,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的倘屹。 我是一名探鬼主播银亲,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼纽匙!你這毒婦竟也來(lái)了务蝠?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤烛缔,失蹤者是張志新(化名)和其女友劉穎馏段,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體践瓷,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡院喜,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了晕翠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片喷舀。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖淋肾,靈堂內(nèi)的尸體忽然破棺而出硫麻,到底是詐尸還是另有隱情,我是刑警寧澤樊卓,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布拿愧,位于F島的核電站,受9級(jí)特大地震影響简识,放射性物質(zhì)發(fā)生泄漏赶掖。R本人自食惡果不足惜感猛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望奢赂。 院中可真熱鬧陪白,春花似錦、人聲如沸膳灶。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)轧钓。三九已至序厉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間毕箍,已是汗流浹背弛房。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留而柑,地道東北人文捶。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像媒咳,于是被迫代替她去往敵國(guó)和親粹排。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容