zoukankan      html  css  js  c++  java
  • Fresco 源码分析(二) Fresco客户端与服务端交互(1) 解决遗留的Q1问题

    4.2 Fresco客户端与服务端的交互(一) 解决Q1问题##

    从这篇博客开始,我们开始讨论客户端与服务端是如何交互的,这个交互的入口,我们从Q1问题入手(博客按照这样的问题入手,是因为当时我也是从这里好奇,才开始分析如何交互的,这样避免了思维的跳跃性)
    既然我们想从这里入手,那么还是以controller的请求入手,因为请求是从这里发出去的,那么肯定入口就存在于AbstractDraweeController.submitRequest()方法,上源码: 在刚刚查看源码时,我们并没有提及到getDataSource()方法是如何实现的,我们先再浏览一遍submitRequest方法

    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);
      }
    

    在看到getDataSource方法时,我们查看其方法,发现是抽象方法,查看类的继承关系图,得知,实现类有两个PipelineDraweeController和VolleyDraweeController,这个就遇到点困难了,到底采用的是哪个呢?到这里就卡壳了,那么如何处理呢?我们要回到我们起点了,就是在写demo的时候,我们一般在Application 的实现类中的onCreate方法中,调用Fresco.initialize()方法,不得不从这里开始看,因为所有的初始化信息,是在这里实现的(这可不是步步高打火机,那里不会点哪里,哈哈哈)

    4.2.1 Fresco初始化的过程##

    为了要了解getDataSource()方法使用的是哪个实现类,我们从Fresco.initialize()方法入手,分析Fresco初始化的过程
    在书写demo的时候,从官方的说明中,已经得知,一般是在Application的onCreate()方法中调用Fresco.initialize()方法,那么这里做了什么样的操作呢?从方法名也可知,这是做了初始化,但是具体需要初始化那些信息呢?
    *** Fresco.initialize() 源码 ***

      /** Initializes Fresco with the default config. */
      public static void initialize(Context context) {
        ImagePipelineFactory.initialize(context);
        initializeDrawee(context);
      }
    

    从上边的源码可知,初始化了两部分信息

    1. ImagePipelineFactory做了初始化
    2. 初始化了Drawee组件信息

    note: 个人查看他人代码,可将这个过程当做图来处理,可以做广度查看,也可以按照深度查看,个人建议,广度做了解,了解当前方法的大致流程(对于书写比较规范的框架,一般是见名知意的)然后做每个方法的深度遍历,便了解,边做笔记。

    上述已经得知,先做ImagePipelineFactory的初始化,然后初始化Drawee组件,那么就先查看ImagePipelineFactory的初始化

    4.2.1.1 ImagePipelineFactory的初始化

    *** ImagePipelineFactory.initialize() 源码 ***

      /** Initializes {@link ImagePipelineFactory} with default config. */
      public static void initialize(Context context) {
        initialize(ImagePipelineConfig.newBuilder(context).build());
      }
    
      /** Initializes {@link ImagePipelineFactory} with the specified config. */
      public static void initialize(ImagePipelineConfig imagePipelineConfig) {
        sInstance = new ImagePipelineFactory(imagePipelineConfig);
      }
    
      public ImagePipelineFactory(ImagePipelineConfig config) {
        mConfig = Preconditions.checkNotNull(config);
      }
    

    初始化过程,构造了一个ImagePipelineConfig,然后将创建的ImagePipelineConfig用于初始化ImagePipelineFactory,即新建了一个ImagePipelineFactory,新创建的ImagePipelineFactory保存了ImagePipelineConfig的实例

    note:这里再次使用了构造者模式

    下面需要关注的就变为了ImagePipelineConfig.newBuilder(context).build()的操作

    *** ImagePipelineConfig.newBuilder(context).build()的源码 ***

      public static Builder newBuilder(Context context) {
        return new Builder(context);
      }
    
    
     public static class Builder {
    	......
    
        private Builder(Context context) {
          // Doesn't use a setter as always required.
          mContext = Preconditions.checkNotNull(context);
        }
    
    
    	......	   
    
        public ImagePipelineConfig build() {
          return new ImagePipelineConfig(this);
        }
      }
    

    从查看ImagePipelineConfig的上述源码,得知,核心的初始化方法,在Builder.build()方法中,而在builder中创建了一个ImagePipelineConfig对象,而依附的对象为builder,这就到了ImagePipelineConfig的核心处

     private ImagePipelineConfig(Builder builder) {
        mBitmapMemoryCacheParamsSupplier =
            builder.mBitmapMemoryCacheParamsSupplier == null ?
                new DefaultBitmapMemoryCacheParamsSupplier(
                    (ActivityManager) builder.mContext.getSystemService(Context.ACTIVITY_SERVICE)) :
                builder.mBitmapMemoryCacheParamsSupplier;
        mCacheKeyFactory =
            builder.mCacheKeyFactory == null ?
                DefaultCacheKeyFactory.getInstance() :
                builder.mCacheKeyFactory;
        mContext = Preconditions.checkNotNull(builder.mContext);
        mEncodedMemoryCacheParamsSupplier =
            builder.mEncodedMemoryCacheParamsSupplier == null ?
                new DefaultEncodedMemoryCacheParamsSupplier() :
                builder.mEncodedMemoryCacheParamsSupplier;
        mExecutorSupplier =
            builder.mExecutorSupplier == null ?
                new DefaultExecutorSupplier() :
                builder.mExecutorSupplier;
        mImageCacheStatsTracker =
            builder.mImageCacheStatsTracker == null ?
                NoOpImageCacheStatsTracker.getInstance() :
                builder.mImageCacheStatsTracker;
        mIsPrefetchEnabledSupplier =
              builder.mIsPrefetchEnabledSupplier == null ?
                  new Supplier<Boolean>() {
                    @Override
                    public Boolean get() {
                      return true;
                    }
                  } :
                  builder.mIsPrefetchEnabledSupplier;
        mMainDiskCacheConfig =
            builder.mMainDiskCacheConfig == null ?
                getDefaultMainDiskCacheConfig(builder.mContext) :
                builder.mMainDiskCacheConfig;
        mMemoryTrimmableRegistry =
            builder.mMemoryTrimmableRegistry == null ?
                NoOpMemoryTrimmableRegistry.getInstance() :
                builder.mMemoryTrimmableRegistry;
        mPoolFactory =
            builder.mPoolFactory == null ?
                new PoolFactory(PoolConfig.newBuilder().build()) :
                builder.mPoolFactory;
        mProgressiveJpegConfig =
            builder.mProgressiveJpegConfig == null ?
                new SimpleProgressiveJpegConfig() :
                builder.mProgressiveJpegConfig;
        mRequestListeners =
            builder.mRequestListeners == null ?
                new HashSet<RequestListener>() :
                builder.mRequestListeners;
        mResizeAndRotateEnabledForNetwork = builder.mResizeAndRotateEnabledForNetwork;
        mSmallImageDiskCacheConfig =
            builder.mSmallImageDiskCacheConfig == null ?
                mMainDiskCacheConfig :
                builder.mSmallImageDiskCacheConfig;
    
        mAnimatedDrawableUtil = new AnimatedDrawableUtil();
        AnimatedDrawableBackendProvider animatedDrawableBackendProvider =
            new AnimatedDrawableBackendProvider() {
          @Override
          public AnimatedDrawableBackend get(AnimatedImageResult imageResult, Rect bounds) {
            return new AnimatedDrawableBackendImpl(mAnimatedDrawableUtil, imageResult, bounds);
          }
        };
        GingerbreadBitmapFactory factoryGingerbread = new GingerbreadBitmapFactory();
        DalvikBitmapFactory factoryICS = new DalvikBitmapFactory(
            new EmptyJpegGenerator(mPoolFactory.getPooledByteBufferFactory()),
            mPoolFactory.getSharedByteArray());
        ArtBitmapFactory factoryLollipop =
            new ArtBitmapFactory(mPoolFactory.getBitmapPool());
        mPlatformBitmapFactory =
            new PlatformBitmapFactory(
                factoryGingerbread,
                factoryICS,
                factoryLollipop);
    
        mAnimatedImageFactory = builder.mAnimatedImageFactory == null ?
            new AnimatedImageFactory(animatedDrawableBackendProvider, mPlatformBitmapFactory) :
            builder.mAnimatedImageFactory;
    
        mImageDecoder =
            builder.mImageDecoder == null ?
                new ImageDecoder(mAnimatedImageFactory, mPlatformBitmapFactory) :
                builder.mImageDecoder;
        mNetworkFetcher =
            builder.mNetworkFetcher == null ?
                new HttpUrlConnectionNetworkFetcher() :
                builder.mNetworkFetcher;
      }
    

    上述源码是ImagePipelineConfig的构造,发现此处初始化涉及的信息比较多,为了方便理解,我们先从名称上做一下理解,一会儿用到的时候,再反过来查看相关的详情信息
    此类的名称特别形象,就是ImagePipleline的配置类,这其中配置了比较核心的几项

    1. mBitmapMemoryCacheParamsSupplier 内存缓存数据的策略
    2. mCacheKeyFactory 缓存键值对的获取
    3. mExecutorSupplier 获取本地读写线程池,网络数据线程池,解码线程池,以及后台线程池
    4. mImageDecoder 解码器
    5. 网络数据获取器
      ......

    ImagePipeLineConfig是一个比较核心的类,通过这个,我们可以得知,Freco初始化时,配置了大量的策略,可配置项很多,也就让我们的使用更加灵活和易于拓展

    4.2.1.2 Fresco.initializeDrawee()的过程

      private static void initializeDrawee(Context context) {
        sDraweeControllerBuilderSupplier = new PipelineDraweeControllerBuilderSupplier(context);
        SimpleDraweeView.initialize(sDraweeControllerBuilderSupplier);
      }
    

    从上述可知,构造了一个sDraweeControllerBuilderSupplier,然后将这个supplier用于初始化SimpleDraweeView
    哎!找到了,发现使用的是PipelineDraweeControllerBuilderSupplier,是不是分析到这里我们就可以结束了?答案是我们只是找到了用于初始化SimpleDraweeView的supplier是PipelineDraweeControllerBuilderSupplier,但是这个做的是怎么样的一个操作呢?我们下节再讨论
    下篇链接: Fresco 源码分析(二) Fresco.initializeDrawee()分析 续 http://www.cnblogs.com/pandapan/p/4659960.html

    安卓源码分析群: Android源码分析QQ1群号:164812238

  • 相关阅读:
    Qt编程规范
    QtZint编译过程记录(要使用 QTMAKE_CFLAGS += /TP 参数)
    中科同向备份软件Heartsone-backup(足足16个软件,可差异化备份虚拟机)
    单例(Singleton)模式
    COFF/PE文件结构
    模板样式优化
    如何测试网页的登录页面
    enode框架step by step之消息队列的设计思路
    服务承载
    CSS文件和Javascript文件的压缩
  • 原文地址:https://www.cnblogs.com/pandapan/p/4646786.html
Copyright © 2011-2022 走看看