Flutter是如何加载图片的

Flutter是如何加载图片的


首先我们看一下Flutter的线程模型:

Platform Thread:android和iOS当中应用的主线程,在Flutter当中负责一些engine接口的调用,engine会去处理应用的一些生命周期事件,比如前后台切换,VC和activity的生命周期事件,用户的一些手势输入也是通过Platform Thread输入给Flutter engine的。
UI Thread:我们也管它叫Flutter的主线程或dart线程,虽然管它叫dart线程,其实这里不止运行dart代码,我们的业务dart代码,包括上层的dart framework,由dart framework控制的整个widget tree,renderobject tree以及调用到的C++层的skia,layer tree的管理,其实都是在UI Thread。
IO Thread:IO线程在Flutter里其实就比较简单,负责图片上传GPU的工作。图片其实是在IO Thread异步上传,形成GPU的纹理。
GPU Thread:GPU的异步调用,绘制上屏。
Work Thread:会做一些杂事,与图片相关的工作就是图片的解码是在Work Thread中进行的。

在Flutter引擎启动的时候,IO Thread会创建ShellIOManager对象,ShellIOManager会创建一个OpenGL的context,同时GPU线程也会创建一个自己的context,这两个context是放到一个Share Group里,它们可以去共享纹理,纹理对象在Flutter里其实是一个C++的对象,它有一个特点就是在底层不会对这个纹理对象进行缓存,这个纹理对象是通过dart层的dart对象进行引用计数的,也就是说通过Dart VM的dart对象来管理底层C++层的纹理对象的生命周期。
总结起来,Flutter它的图片是在Work Thread进行解码,解码完成以后是在IO Thread上传到共享的context中生成纹理,这个纹理可以被GPU Thread所使用,所有的纹理对象是在dart层做引用计数的,底层是不会缓存的。

那么看一下Flutter从加载图片到图片绘制出来相关类的一个关系图:
Flutter是如何加载图片的_第1张图片
我们一般会使用Image Widget的network方法去加载一个网络图片,Image Widget的ImageState有两个功能,一个是驱动NetworkImage(provider)去下载图片,再有是调用setState去管理底层的renderObject,renderObject最终去负责渲染上屏。
ImageState会调用自己的resolveImage方法,resolveImage会调用ScrollAwareImageProvider的resolve方法去取得ImageStream对象,ImageStream对象会把自己添加到StreamCompleter里作为一个Listener,一个StreamCompleter可以添加多个ImageStream,
当图片完成时会给所有Listener发事件,ImageState接收到事件以后会拿到纹理对象做绘制,NetworkImage会在自己的resolve方法里异步做图片的下载,下载完成以后我们就拿到了图片的bytes,之后会通过dart和C++层的接口函数instantiateImageCodec创建C++层解码器的对象codec,codec拿到图片的流以后会在底层做一个解码工作,图片的流会被抛到worker线程去做解码,解码完成以后我们会拿到解码后的位图,然后把位图丢到IO线程进行上传,形成GPU纹理,纹理形成以后又会返回给UI线程也就是dart的主线程去使用,上层拿到图片纹理以后,会调用ImageState的setState,把纹理对象传给底层的renderObject,renderObject的paint方法完成以后,图片就绘制到屏幕上了。

你可能感兴趣的:(Flutter是如何加载图片的)