Fresco 源碼分析(四) 後臺數據返回到前臺的處理

AbstractDraweeController.submitRequest()源碼分析 續

這部分的邏輯之前已經分析了一部分,在此我們分析一下關於回調處理的部分
……
1. 獲取到數據源
2. 註冊數據源的觀察者(這裏使用的回調是mUiThreadImmediateExecutor–>ui的線程池,關於這個線程池標記爲Q8,這個是很好的一個封裝,將UI線程封裝爲了線程池)
3. 對於返回的數據結果的處理體現在接口中DataSubscriber

protected void submitRequest() {
    mEventTracker.recordEvent(Event.ON_DATASOURCE_SUBMIT);
    getControllerListener().onSubmit(mId, mCallerContext);
    mSettableDraweeHierarchy.setProgress(0, true);
    mIsRequestSubmitted = true;
    mHasFetchFailed = false;
    mDataSource = getDataSource();
    if (FLog.isLoggable(FLog.VERBOSE)) {
      FLog.v(
          TAG,
          "controller %x %s: submitRequest: dataSource: %x",
          System.identityHashCode(this),
          mId,
          System.identityHashCode(mDataSource));
    }
    final String id = mId;
    final boolean wasImmediate = mDataSource.hasResult();
    final DataSubscriber<T> dataSubscriber =
        new BaseDataSubscriber<T>() {
          @Override
          public void onNewResultImpl(DataSource<T> dataSource) {
            // isFinished must be obtained before image, otherwise we might set intermediate result
            // as final image.
            boolean isFinished = dataSource.isFinished();
            float progress = dataSource.getProgress();
            T image = dataSource.getResult();
            if (image != null) {
              onNewResultInternal(id, dataSource, image, progress, isFinished, wasImmediate);
            } else if (isFinished) {
              onFailureInternal(id, dataSource, new NullPointerException(), /* isFinished */ true);
            }
          }
          @Override
          public void onFailureImpl(DataSource<T> dataSource) {
            onFailureInternal(id, dataSource, dataSource.getFailureCause(), /* isFinished */ true);
          }
          @Override
          public void onProgressUpdate(DataSource<T> dataSource) {
            boolean isFinished = dataSource.isFinished();
            float progress = dataSource.getProgress();
            onProgressUpdateInternal(id, dataSource, progress, isFinished);
          }
        };
    mDataSource.subscribe(dataSubscriber, mUiThreadImmediateExecutor);
  }

再看回調的相關方法之前,先看看BaseDataSubscriber的相關類的繼承體系
這個的設計方式與Consumer的設計模式類似,都是先是一個接口,然後抽象的一個實現Abstract***類中實現這些接口,然後暴露出相關的實現方法impl,這種設計的方式有很多好處,很值得我們借鑑,實現了面向接口的編程,同時,通用的邏輯又在抽象類中得以實現,接口相關的內容供外界調用,Impl的相關方法供內部實現.

BaseDataSubscriber類的源碼

 @Override
  public void onNewResult(DataSource<T> dataSource) {
    try {
      onNewResultImpl(dataSource);
    } finally {
      if (dataSource.isFinished()) {
        dataSource.close();
      }
    }
  }

  @Override
  public void onFailure(DataSource<T> dataSource) {
    try {
      onFailureImpl(dataSource);
    } finally {
      dataSource.close();
    }
  }

  @Override
  public void onCancellation(DataSource<T> dataSource) {
  }

  @Override
  public void onProgressUpdate(DataSource<T> dataSource) {
  }

  protected abstract void onNewResultImpl(DataSource<T> dataSource);

  protected abstract void onFailureImpl(DataSource<T> dataSource);

回到我們的正題,查看AbstractDraweeController的匿名BaseDataSubscriber實現類

* 匿名BaseDataSubscriber實現類相關源碼*

還是以處理成功爲例,這裏會調用AbstractDraweeController的onNewResultInternal方法

        new BaseDataSubscriber<T>() {
          @Override
          public void onNewResultImpl(DataSource<T> dataSource) {
            // isFinished must be obtained before image, otherwise we might set intermediate result
            // as final image.
            boolean isFinished = dataSource.isFinished();
            float progress = dataSource.getProgress();
            T image = dataSource.getResult();
            if (image != null) {
              onNewResultInternal(id, dataSource, image, progress, isFinished, wasImmediate);
            } else if (isFinished) {
              onFailureInternal(id, dataSource, new NullPointerException(), /* isFinished */ true);
            }
          }
          @Override
          public void onFailureImpl(DataSource<T> dataSource) {
            onFailureInternal(id, dataSource, dataSource.getFailureCause(), /* isFinished */ true);
          }
          @Override
          public void onProgressUpdate(DataSource<T> dataSource) {
            boolean isFinished = dataSource.isFinished();
            float progress = dataSource.getProgress();
            onProgressUpdateInternal(id, dataSource, progress, isFinished);
          }

AbstractDraweeController.onNewResultInternal() 源碼分析

邏輯如下:
 
1. 檢查是否是自己想要的結果,如果不是,直接釋放資源(感覺這塊像是在fix bug 一樣,沒有注意到這塊爲何會如此處理,查看代碼說是因爲後續還是會返回之前的一些結果,所以這裏做了這樣的判斷)
2. 根據返回的image信息,生成drawable
3. 如果是已經請求完成的信息,便直接將mDataSource設置爲null(個人有點疑惑,命名在release的時候,會釋放dataSource的信息,這裏卻直接設置爲空,可能是爲了第一步的資源檢查或者說單純的釋放引用,讓內存及時回收,如果有理解的請留言回覆我,感謝)
4. 將drawable對象交給hierarchy來處理
5. 釋放drawable的相關信息(這裏指的是緩存之類的信息,爲了節省內存空間,而沒有釋放drawble)

 private void onNewResultInternal(
      String id,
      DataSource<T> dataSource,
      @Nullable T image,
      float progress,
      boolean isFinished,
      boolean wasImmediate) {
    // ignore late callbacks (data source that returned the new result is not the one we expected)
    if (!isExpectedDataSource(id, dataSource)) {
      logMessageAndImage("ignore_old_datasource @ onNewResult", image);
      releaseImage(image);
      dataSource.close();
      return;
    }
    mEventTracker.recordEvent(
        isFinished ? Event.ON_DATASOURCE_RESULT : Event.ON_DATASOURCE_RESULT_INT);
    // create drawable
    Drawable drawable;
    try {
      drawable = createDrawable(image);
    } catch (Exception exception) {
      logMessageAndImage("drawable_failed @ onNewResult", image);
      releaseImage(image);
      onFailureInternal(id, dataSource, exception, isFinished);
      return;
    }
    T previousImage = mFetchedImage;
    Drawable previousDrawable = mDrawable;
    mFetchedImage = image;
    mDrawable = drawable;
    try {
      // set the new image
      if (isFinished) {
        logMessageAndImage("set_final_result @ onNewResult", image);
        mDataSource = null;
        mSettableDraweeHierarchy.setImage(drawable, 1f, wasImmediate);
        getControllerListener().onFinalImageSet(id, getImageInfo(image), getAnimatable());
        // IMPORTANT: do not execute any instance-specific code after this point
      } else {
        logMessageAndImage("set_intermediate_result @ onNewResult", image);
        mSettableDraweeHierarchy.setImage(drawable, progress, wasImmediate);
        getControllerListener().onIntermediateImageSet(id, getImageInfo(image));
        // IMPORTANT: do not execute any instance-specific code after this point
      }
    } finally {
      if (previousDrawable != null && previousDrawable != drawable) {
        releaseDrawable(previousDrawable);
      }
      if (previousImage != null && previousImage != image) {
        logMessageAndImage("release_previous_result @ onNewResult", previousImage);
        releaseImage(previousImage);
      }
    }
  }

在這裏我們最關心的就是drawable交給hierarchy後是如何處理的

那就繼續跟蹤,

GenericDraweeHierarchy.setImage()

  @Override
  public void setImage(Drawable drawable, float progress, boolean immediate) {
    drawable = maybeApplyRoundingBitmapOnly(mRoundingParams, mResources, drawable);
    drawable.mutate();
    mActualImageSettableDrawable.setDrawable(drawable);
    mFadeDrawable.beginBatchMode();
    fadeOutBranches();
    fadeInLayer(mActualImageIndex);
    setProgress(progress);
    if (immediate) {
      mFadeDrawable.finishTransitionImmediately();
    }
    mFadeDrawable.endBatchMode();
  }

其實在這裏面完成了圖像的展示,但是單純的如此查看這段邏輯,我們還是會感覺到有點迷惑,只是發現了drawable的一些變化,然後就沒有了,那麼處理的邏輯在哪裏呢?其實這個是drawable的強大之處(爲什麼強大,大家可以先看看google android的官方網站上關於drawable的介紹以及再看看鴻洋大神關於drawable的一些案例介紹http://blog.csdn.net/lmj623565791/article/details/43752383),fresco自己又實現了一套drawable的繼承體系,專門來處理ui上的一些變化效果,,接下來我也會提及一部分這方面的知識,便於大家理解.drawable的部分插敘完成後,我們繼續分析Hierachy的相關知識

下篇鏈接:Fresco 源碼分析(四) 後臺數據返回到前臺的處理 - Drawable體系的介紹(1)(http://blog.csdn.net/IEYUDEYINJI/article/details/48879647)
安卓源碼分析羣: Android源碼分析QQ1羣號:164812238

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章