美文网首页
2019-11-17

2019-11-17

作者: Y哟嚯Y | 来源:发表于2019-11-17 08:51 被阅读0次

    Glide 4.8源码粗略分析(人太懒,以后有时间了再配图和排版)
    1:with方法(返回一个RequestManager对象,主要用于管理加载图片的操作)
    方法内部会实例化一个GlideBuilder对象,
    会设置默认的RequestOptions,
    这个RequestOptions类主要用来设置加载图片的缓存策略,图片加载的大小,动画,以及其他状态的占位图等
    然后调用GlideBuilder的build方法做一些初始化的工作,
    比如用来管理加载图片线程的线程池,构建RequestManager对象的RequestManagerFactory
    还有实例化一个Engine类,而这个类的load方法是开启图片加载的入口(后面的into方法会继续说到)
    接着会实例化一个RequestManagerRetriever对象,用来管理RequestManager
    最后build方法会返回一个Glide对象,上面的部分属性也会当做参数传入glide类中,比如Engine,RequestManagerRetriever,RequestOptions,

    因为with方法传入的参数是Context,接着通过getApplicationContext()获取application,来注册一个registerComponentCallbacks接口
    通过这个接口,可以监听系统内存的状态调整,如果系统内存吃紧或者应用位于后台时,可以选择性释放一些图片的内存缓存

    实例化Glide对象之后返回RequestManagerRetriever对象,接着调用RequestManagerRetriever的get方法返回一个RequestManager,而实例化RequestManager时,又将Glide对象传入,可以通过这个对象获取之前初始化的其他对象
    而在实例化RequestManager之前,做了一个监听Activity生命周期的操作,
    主要通过给Activity绑定一个无ui视图的fragment来监听生命周期,在onDestroy时及时释放图片缓存和中断一些图片请求,从而避免消耗过多的内存

    此时with方法最终返回的是一个RequestManager对象,接着就进入load方法
    2:load方法 (主要返回一个RequestBuilder对象,用于加载图片之前的准备工作)
    方法的参数有好几种,比如bitmap,byte[],file,drawable,uri,这里主要以String 网络请求地址为例
    load方法内部默认会调用RequestManager的asDrawable来实例化RequestBuilder对象,并且将RequestManager持有的glide对象传入,
    RequestBuilder的构造方法内部也会将RequestManager的RequestOptions赋值给RequestBuilder(RequestManager的RequestOptions是由Glide对象传给RequestManager的)
    接着再将load方法的参数赋值给RequestBuilder内部Object类型的model属性,至此load方法结束,
    如果你想自行设置加载图片的某些属性,可以实例化RequestOptions,然后在load方法之后调用apply方法将它传入,会在RequestBuilder中将新的RequestOptions属性覆盖给旧的RequestOptions

    3:into方法(主要是通过之前的设置来做获取图片和加载图片的操作)
    传入的参数以ImageView为例
    ImageView会当做一个参数传入glideContext的buildImageViewTarget中(因为RequestBuilder持有Glide,Glide持有glideContext,所以RequestBuilder内部可以调用glideContext的方法),
    同时会根据之前load方法中默认调用的asDrawable构建一个DrawableImageViewTarget(ImageViewTarget的子类)
    因为ImageViewTarget含有ImageView,所以最后获取图片之后,会回调抽象方法setResource来将图片设置到imageview上面
    构建ImageViewTarget之后,又将它当做一个参数传入RequestBuilder中的另外一个into方法,
    根据ImageViewTarget,RequestOptionsListenter,RequestOptions构建出一个Request的实现类:SingleRequest,
    然后和ImageViewTarget之前设置的Request对比,如果是一样的以及不跳过内存缓存获取图片,主要是通过SingleRequest中的部分属性进行比对(比如设置的图片宽高,requestOptions属性,加载的优先级),如果一致,则认为两个SingleRequest,是一样的
    ,如果两者Request一致,则将刚刚构建的request置空,然后继续判断之前的request是否还在获取图片,如果是则返回,如果没有就调用request的begin方法(同下),开始后续操作
    ,如果两者Request不一致,则将之前的request置空,然后将刚刚的request设置给ImageViewTarget(放在imageview的tag中,这也是为什么加载图片的时候,如果在不设置key的情况下给imageview设置tag,glide会报错的原因,因为会覆盖glide设置的request具体实现类)
    然后requestManager调用track方法,接着调用request的begin方法进行后续操作(同上),这个时候来到SingleRequest(request的实现类)的begin方法中,
    begin方法中主要做两个判断,一个是设置的图片加载宽高是否有效,一个是目前的图片加载状态,如果状态是加载完成,那么直接将内存中的resource数据返回
    如果设置的宽高小于等于0,则通过ViewTarget去获取Imageview的宽高,如过imageview的宽高都是wrap_content,这获取屏幕的高度作为要加载的图片宽高,
    接着又会调用SingleRequest中的onSizeReady方法,因为在glide的with方法中实例化了一个Engine对象,这个engine对象随着Glide对象一直传到了SingleRequest中,此时engine调用load方法,开始获取图片的操作

    通过glide外部的load方法传进来的参数(也就是RequestBuilder的model属性,此处为图片的url地址)
    和一个EmptySignature的实例(Key的具体实现类),以及图片宽高和requestoptions构建一个Enginekey,根据这个key先从活动缓存获取图片
    ,如果没有继续从lrucache缓存获取图片,如果还没有,则实例化一个EngineJob和DecodeJob,通过EngineJob内部的线程池开启一个线程去获取,线程内部的操作在DecodeJob的run方法中执行,

    开始构建一个DataFetcherGenerator的具体实现类,调用它的startNext方法来判断是否能够从磁盘获取图片,如果有,则从磁盘获取图片数据,然后进行一些列的回调操作,最后ImageViewTarget回调方法中设置图片
    如果磁盘没有数据,则开启网络请求获取inputsteam数据,然后进行一些列回调,将数据缓存到磁盘,然后从磁盘获取数据,获取数据时通过imageheadparse来解析图片格式,因为构建Request时有传入ImageViewTarget,所以最后可以通过ImageViewTarget回调方法将数据传入实现图片加载

    相关文章

      网友评论

          本文标题:2019-11-17

          本文链接:https://www.haomeiwen.com/subject/rotpictx.html