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);
}
从上边的源码可知,初始化了两部分信息
- ImagePipelineFactory做了初始化
- 初始化了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的配置类,这其中配置了比较核心的几项
- mBitmapMemoryCacheParamsSupplier 内存缓存数据的策略
- mCacheKeyFactory 缓存键值对的获取
- mExecutorSupplier 获取本地读写线程池,网络数据线程池,解码线程池,以及后台线程池
- mImageDecoder 解码器
- 网络数据获取器
......
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
Fresco 源码分析(二) Fresco客户端与服务端交互(1) 解决遗留的Q1问题的更多相关文章
- Fresco 源码分析(二) Fresco客户端与服务端交互(3) 前后台打通
4.2.1.2.4 PipelineDraweeControllerBuilder.obtainController()源码分析 续 上节中我们提到两个核心的步骤 obtainDataSourceSu ...
- Fresco 源码分析(二) Fresco客户端与服务端交互(2) Fresco.initializeDrawee()分析 续
4.2.1.2 Fresco.initializeDrawee()的过程 续 继续上篇博客的分析Fresco.initializeDrawee() sDraweeControllerBuilderSu ...
- Fresco 源码分析(三) Fresco服务端处理(1) ImagePipeline为何物
4.3 服务端的处理 备注: 因为是分析,而不是设计,所以很多知识我们类似于插叙的方式叙述,就是用到了哪个知识点,我们再提及相关的知识点,如果分析到了最后,我想想是不是应该将这个架构按照设计的方式,重 ...
- Fresco 源码分析(三) Fresco服务端处理(2) Producer具体实现的内容
我们以mProducerFactory.newNetworkFetchProducer()为例,因为这些创建新的producer的方式类似,区别在于是否有包装的处理器,即如果当前处理器中没有正在处理的 ...
- motan源码分析四:客户端调用服务
在第一章中,我们分析了服务的发布与注册,本章中将简单的分析一下客户端调用服务的代码及流程,本文将以spring加载的方式进行分析. 1.在DemoRpcClient类的main()方法中加载类: Ap ...
- Fresco 源码分析(三) Fresco服务端处理(3) DataSource到Producer的适配器逻辑以及BitmapMemoryCacheProducer处理的逻辑
4.3.1.2.1 Producer和DataSource之间适配器处理的逻辑 还是从程序的入口开始说吧 CloseableProducerToDataSourceAdapter.create() 源 ...
- Fresco 源码分析(一) DraweeView-DraweeHierarchy-DraweeController(MVC) DraweeHierachy+DraweeController的分析
4.1.5.2 模型层DraweeHierachy继承体系以及各个类的作用 DraweeHierachy (I) --| SettableDraweeHierarchy (I) ------| Gen ...
- 框架-springmvc源码分析(二)
框架-springmvc源码分析(二) 参考: http://www.cnblogs.com/leftthen/p/5207787.html http://www.cnblogs.com/leftth ...
- Tomcat源码分析二:先看看Tomcat的整体架构
Tomcat源码分析二:先看看Tomcat的整体架构 Tomcat架构图 我们先来看一张比较经典的Tomcat架构图: 从这张图中,我们可以看出Tomcat中含有Server.Service.Conn ...
随机推荐
- 导师互选系统 Alpha版冲刺总结
导师互选系统 Alpha版冲刺总结 一.设想和目标 我们的软件什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 我们的软件主要是要实现导师和学生双向互选的功能.功能定义清晰明确,在软 ...
- android4.0浏览器在eclipse中编译的步骤
工程源码: 注意: 如果下载已经修过的源码,只要进行3.4.8步骤就应该可以了. eclipse版本:adt-bundle-windows (Android Developer Tools Build ...
- 循序渐进Linux 3:Linux下软件安装与管理
一.源码安装 ./configuremakemake install 二.RPM包 1. 安装软件包 rpm -i [辅助选项] file1.rpm file2.rpm主选项 -i: install, ...
- UVA10118(记忆化搜索 + 好题)
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=19440 题意,4堆不同颜色的糖果,每堆N个,从堆上往下拿,放入一个最大装5个 ...
- easyUI框架之学习记录汇总
在添加完之后,可以使用 $.parser.parse();这个方法进行处理:(1) 对整个页面重新渲染: $.parser.parse(); (2) 渲染某个特定的objectvar targetOb ...
- std::auto_ptr
auto_ptr是C++标准库中(<utility>)为了解决资源泄漏的问题提供的一个智能指针类模板(注意:这只是一种简单的智能指针) auto_ptr的实现原理其实就是RAII,在构造的 ...
- Mvc3提交表格验证(转载)
Model层:using System;using System.Collections.Generic;using System.Linq;using System.Web;using System ...
- 域名在微信朋友圈内分享需要ICP备案 杜绝不良信息传播
就在刚刚,腾讯微信团队发布公告表示域名在朋友圈内分享需要ICP备案,杜绝打击不良互联网信息的传播.公告称根据互联网管理相关规定,即日起在微信朋友圈内分享的域名,请在2014年12月31日前完成ICP备 ...
- HDFS深入浅析
导读 Hadoop分布式文件系统(HDFS)被设计成适合运行在通用硬件(commodity hardware)上的分布式文件系统.它和现有的分布式文件系统有很多共同点.但同时,它和其他的分布式文件系统 ...
- Unity游戏开发之“屏幕截图”
原地址:http://sygame.lofter.com/post/117105_791680 在unity游戏开发中,可能会遇到在游戏中截屏的效果.这儿提供两种截屏方法.(方法二提供显示截图缩略图代 ...