Android图片加载框架Fresco分析(八)

Fresco的图片显示流程:

DraweeView中的OnAttachedToWindow()方法中,会调用到DraweeHolder的onAttach()方法。DraweeHolder相当于View的管家。通过这个方法看出来,View在attached的时候就已经调用了holder的onAttach,而在这个onAttach中又会调用到attachController方法,进而调用controller的onAttach的方法。再进去看一下controller的attach方法里做了什么

@Override
public void onAttach() {
  if (FLog.isLoggable(FLog.VERBOSE)) {
    FLog.v(
        TAG,
        "controller %x %s: onAttach: %s",
        System.identityHashCode(this),
        mId,
        mIsRequestSubmitted ? "request already submitted" : "request needs submit");
  }
  mEventTracker.recordEvent(Event.ON_ATTACH_CONTROLLER);
  Preconditions.checkNotNull(mSettableDraweeHierarchy);
  mDeferredReleaser.cancelDeferredRelease(this);
  mIsAttached = true;
  if (!mIsRequestSubmitted) {
    submitRequest();
  }
}

controller的onAttach方法出现在抽象类(AbstractDraweeController)中,在这里明显能够看出来submitRequest()调用了请求去下载图片。

进到submitRequest方法中的代码可以看到一个mSettableDraweeHierarchy,这个Hierarchy是从SimpleDraweeView的父类GenericDraweeView里之前设置好的。同时,controller也会持有这个Hierarchy(之前说明过hierarchy就是用来显示图片和加载进度等)。再往下可以看到

mDataSource = getDataSource();

getDataSource便是将之前解析五中的流程都走了一遍。相当于得到了DataSource。其实最开始是很多的Producer,之后通过ProducerToDataSourceAdapter类将Producer转换成了DataSource。

Android图片加载框架Fresco分析(七)

ImagePipeline类中的

/**
 * Submits a request for bitmap cache lookup.
 *
 * @param imageRequest the request to submit
 * @return a DataSource representing the image
 */
public DataSource<CloseableReference<CloseableImage>> fetchImageFromBitmapCache(
    ImageRequest imageRequest,
    Object callerContext) {
  try {
    Producer<CloseableReference<CloseableImage>> producerSequence =
        mProducerSequenceFactory.getDecodedImageProducerSequence(imageRequest);
    return submitFetchRequest(
        producerSequence,
        imageRequest,
        ImageRequest.RequestLevel.BITMAP_MEMORY_CACHE,
        callerContext);
  } catch (Exception exception) {
    return DataSources.immediateFailedDataSource(exception);
  }
}

Android Studio peer not authenticated 问题解决

导入项目的时候发现了一个问题,项目导入完成了,但是一直在刷新,刷新完成后,一直提示

refresh failed xxx project
Error:Couse:peer not authenticated

经过查询Studi的log文件(D:\Users\Administrator.AndroidStudioPreview1.4\system\log)发现,是缺少javassist-3.16.1-GA.jar文件,从正常的gradle文件夹中将这个jar包搞过来就正常了。可能是在下载gradle过程中缺少了文件。

Android图片加载框架Fresco分析(六)

fresco图片显示过程分析

SmipleDraweeView中的setImageURI方法中使用到了DraweeController,

public void setImageURI(Uri uri, @Nullable Object callerContext) {
DraweeController controller = mSimpleDraweeControllerBuilder
    .setCallerContext(callerContext)
    .setUri(uri)
    .setOldController(getController())
    .build();
setController(controller);
  }

代码中有个setController,该方法属于父类DraweeView,我们进去该方法看一下:

public void setController(@Nullable DraweeController draweeController) {
mDraweeHolder.setController(draweeController);
super.setImageDrawable(mDraweeHolder.getTopLevelDrawable());
  }

其中可以看出来,最终显示的图片就是mDraweeHolder.getTopLevelDrawable()得到的。在进去DraweeHolder中看一下:

public Drawable getTopLevelDrawable() {
return mHierarchy == null ? null : mHierarchy.getTopLevelDrawable();
  }

Android图片加载框架Fresco分析(五)

fresco请求部分分析

SimpleDraweeView在setImageURI的时候,对controller做了默认设置,虽然是DraweeController,但是其实SimpleDraweeView使用到的真正的Controller类是PipeLineDraweeControllerBuilder:

public void setImageURI(Uri uri, @Nullable Object callerContext) {
  DraweeController controller = mSimpleDraweeControllerBuilder
  .setCallerContext(callerContext)
  .setUri(uri)
  .setOldController(getController())
  .build();
  setController(controller);
}

其中的build()方法便是调用了controller的抽象建造者AbstrateDraweeControllerBuilder类中的build()方法:

  public AbstractDraweeController build() {
    validate();
    // if only a low-res request is specified, treat it as a final request.
    if (mImageRequest == null && mMultiImageRequests == null && mLowResImageRequest != null) {
      mImageRequest = mLowResImageRequest;
      mLowResImageRequest = null;
    }
    return buildController();
}
  protected AbstractDraweeController buildController() {
    AbstractDraweeController controller = obtainController();
    maybeBuildAndSetRetryManager(controller);
    maybeAttachListeners(controller);
    return controller;
  }

该方法中返回的buildController()会执行到SimpleDraweeView本身使用到的PipeLineDraweeControllerBuilder中的obtainController():

protected PipelineDraweeController obtainController() {
  DraweeController oldController = getOldController();
  PipelineDraweeController controller;
  if (oldController instanceof PipelineDraweeController) {
    controller = (PipelineDraweeController) oldController;
    controller.initialize(
        obtainDataSourceSupplier(),
        generateUniqueControllerId(),
        getCallerContext());
  } else {
    controller = mPipelineDraweeControllerFactory.newController(
        obtainDataSourceSupplier(),
        generateUniqueControllerId(),
        getCallerContext());
  }
  return controller;
}