Fresco解析 (Controller)
来源:互联网 发布:上海英翼传媒 知乎 编辑:程序博客网 时间:2024/05/22 15:09
第一篇 Fresco初始化流程
第二篇 DraweeView, DraweeHierarchy 分析
DraweeController
根据之前的分析,调用SimpleDraweeView.setImageURI()方法就可以显示图片,源码很简单:
public void setImageURI(Uri uri, @Nullable Object callerContext) { DraweeController controller = mSimpleDraweeControllerBuilder .setCallerContext(callerContext) .setUri(uri) .setOldController(getController()) .build(); setController(controller);}
Fresco源码使用MVC架构,Controller在MVC中主要处理逻辑。在setImageURI方法中new了一个Controller实例,然后setContoller图片就可以显示了,所有的逻辑都交给Controller处理了。
public class DraweeView<DH extends DraweeHierarchy> extends ImageView { private DraweeHolder<DH> mDraweeHolder; private void init(Context context) { mDraweeHolder = DraweeHolder.create(null, context); } public void setController(@Nullable DraweeController draweeController) { mDraweeHolder.setController(draweeController); super.setImageDrawable(mDraweeHolder.getTopLevelDrawable()); }}
SimpleDraweeView 的setController方法定义在DraweeView中,将得到的Controller的对象传到DraweeHolder中,上一篇分析在DraweeView初始化时实例化了DraweeHierarchy对象,然后调用setHierarchy()方法也传到了DraweeHolder中。此时DraweeHolder就有了Controller和DraweeHierarchy的引用,而DraweeHolder又是在DraweeView中创建,这样DraweeView就通过直接引用DraweeHolder间接引用了Controller,和DraweeHiearchy。(标准的解耦)。
DraweeHolder调用了Controller的onAttach,下面的操作进到了DraweeController中:
private void attachController() { if (mIsControllerAttached) { return; } mEventTracker.recordEvent(Event.ON_ATTACH_CONTROLLER); mIsControllerAttached = true; if (mController != null && mController.getHierarchy() != null) { mController.onAttach(); } }
DraweeController是一个接口,继承关系如下:
根据继承关系,AbstractDraweeController中实现了onAttach方法:
@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(); } } protected void submitRequest() { mEventTracker.recordEvent(Event.ON_DATASOURCE_SUBMIT); getControllerListener().onSubmit(mId, mCallerContext); //设置进度为0 开始设置图片了 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(); T image = dataSource.getResult(); if (image != null) { onNewResultInternal(id, dataSource, image, 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); } }; //绑定观察者 mDataSource.subscribe(dataSubscriber, mUiThreadImmediateExecutor); }
调用submitRequest()提交了请求。(使用了RxJava中的观察者模式,注册观察者,DataSource内容发生变化,会回调到dataSubscriber中)。
getDataSource()定义在PipelineDraweeController中,代码很简单,从mDataSourceSupplier中取出DataSource。 而mDataSourceSupplier是创建Controller时通过构造方法传进来的,所以得知道Controller是咋创建的。
@Override protected DataSource<CloseableReference<CloseableImage>> getDataSource() { return mDataSourceSupplier.get(); }
Controller创建比较复杂,从网上借鉴了一张流程图(原文链接)
public void setImageURI(Uri uri, @Nullable Object callerContext) { DraweeController controller = mSimpleDraweeControllerBuilder .setCallerContext(callerContext) .setUri(uri) .setOldController(getController()) .build(); setController(controller);}
Supplier的创建主要分下面几步:
1、mSimpleDraweeControllerBuilder是Controller的构建者,调用setUri(uri)时将Uri封装成ImageRequest然后调用super将ImageRequest保存到了AbstractDraweeControllerBuilder中。
@Override public PipelineDraweeControllerBuilder setUri(Uri uri) { return super.setImageRequest(ImageRequest.fromUri(uri)); }
2、在AbstractDraweeControllerBuilder中定义obtainDataSourceSupplier()方法将第一步通过setUri传入的ImageRequest转换成Supplier。
3、SuppliermPipelineDraweeControllerFactory.newController创建一个Controller,把Supplier传到了Controller中。
执行完这三步,当SimpleDraweeView调用setController时,通过Supplier.get()可得到DataSource了。
PS:从上面流程中看到实例化一个Controller,直接或间接调用了四个类,让人看着很蛋疼,Fresco这样写肯定也有他的道理。
之前分析类继承关系时,看到Fresco中不只有一个PipelineDraweeController,还有VolleyDraweeController(将来可能还有更多),这两个Controller都继承AbstractDraweeController。其中AbstractDraweeControllerBuilder的功能是构建一个Controller,build功能是所有的Builder中必备的功能,所以build方法定义在了AbstractDraweeControllerBuilder中。但是Controller有很多种,所以具体构建 Controller的功能交给了各自的继承类,例如通过PipelineDraweeControllerBuilder构建出来PipelineDraweeController。在Builder中再调用各自Controller的工厂类来最终得到一个Controller。
虽然让看代码的很蛋疼,但是代码的层次更清楚,可扩展性也更高,值得借鉴。
到此Controller的分析也就完成了,下次将分析Fresco的网络请求。
- Fresco解析 (Controller)
- Fresco源码解析 - Hierarchy / View / Controller
- Fresco解析 (初始化)
- Fresco解析(DraweeView,DraweeHierarchy)
- Fresco解析
- fresco解析(2)之View
- Fresco源码解析 - DraweeView
- fresco解析之Hierarchy
- Fresco源码解析 - 创建一个ImagePipeline(一)
- Fresco源码解析 - 创建一个ImagePipeline(一)
- Fresco源码解析 - 本地编译
- Character Controller深度解析
- ci Controller.php解析
- kube-controller原理解析
- Fresco
- Fresco
- Fresco
- fresco
- 洛谷Oj-信息传递-拓扑排序+DFS/Tarjan强连通分量
- orientdb实战
- 最小的k个数
- 6-通过Java代码build cube
- eclipse中的jar包----tomcat JRE Referenced Libraries WebApp Libraries lib
- Fresco解析 (Controller)
- 关闭sublime3自动更新(要输入license才会奏效)
- Java学习笔记(18)--关键字this详解
- python函数默认参数使用不当解决方法
- 瑞晟面试记录
- 电商行业开发者如何基于云端构建业务?腾讯云+未来峰会上这样说
- Linux之root初始密码设置
- 构造器的使用
- setContentView 报错空指针异常