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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI老潘信息差

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值