了解Android Glide

192 阅读3分钟

简单使用一下

Glide.with(context).load(url).into(imageView)

1、with(xxx)

该参数是可以是 ApplicationContextActivityFragment,是告诉Glide组件应该依附在哪个组件上

如果传入的是应用全局ApplicationContext那么它的生命周期和整个应用是保持一致的,Glide通过单例持有全局RequestManager进行管理,它没有生命周期回调,操作起来不方便,如果加载图片至Activity的ImageView,但此Activity被销毁了,RequestManager仍旧对ImageView进行赋值会导致空对象引用报错

如果传入的是ActivityFragment则会在其基础上附加一个没有UI的隐藏Fragment

(1)隐藏的Fragment

这个隐藏的Fragment不会显示任何东西,它主要的作用是监听持有者的生命周期回调(onCreateonStart()onStop()onDestroy()等),当持有者调用这些方法时,该隐藏Fragment就会收到通知,随之调用对应RequestManager的方法

(2)RequestManager 是什么

RequestManager是单例的,如果已经被初始化过会直接返回确保当前Activity只有一个RequestManager 来管理其生命周期内的图片请求,如果不存在则会创建一个SupportRequestManagerFragment通过 FragmentManager 将这个新创建的隐藏 Fragment 添加到宿主上,该Fragment会创建一个新的RequestManager 实例,并将其持有,之后所有的处理都是交给RequestManager,它就像一个管家,专门为你处理图片,下面是写的很草率的版本

class NoUIRequestManagerFragment : Fragment() { 

    // 这个就是管家
    private var requestManager: RequestManager? = null

    override fun onCreate(savedInstanceState: Bundle?) { 
        if(requestManager == null) {
           requestManager = RequestManager()
        }
    }
    
    /** 其他生命周期 ...
    
    // 让外部可以获取它所持有的 RequestManager 实例
    fun getRequestManager(): RequestManager {
        return requestManager 
            ?: throw IllegalStateException("RequestManager not initialized") 
    }
}

在外部初始化NoUIRequestManagerFragment没有UI的Fragment后,可以使用

fun getRequestManager() : RequestManager {
    val FRAGMENT_TAG = "xxx" // 1. 尝试从FragmentManager中查找已存在的 NoUIRequestManagerFragment 
    var fragment = supportFragmentManager.findFragmentByTag(FRAGMENT_TAG) as? NoUIRequestManagerFragment
    if(fragment == null){
        fragment = NoUIRequestManagerFragment()
        supportFragmentManager
            .beginTransaction()
            .add(fragment, FRAGMENT_TAG) // 将 Fragment 添加到 Activity 
            .commitNowAllowingStateLoss() // 立即提交,允许在状态丢失后提交
    }
    return fragment.getRequestManager()
}
    override fun onCreate(savedInstanceState: Bundle?) { 
      // 类似Glide.with(context),可以用imageLoader加载图片了
      val imageLoader = getRequestManager()
    }
     
     /** 其他生命周期 ...

2、load(url)

简单讲就是定义需要加载的资源,通过ModelLoader处理不同数据源

(1)缓存查找:内存、磁盘

(2)数据获取:启动DataFetcher去获取图片,这个过程是异步的

3、into(imageView)

经过解码、转换(处理图片API)后的最终 Bitmap 会被封装成一个 Drawable,然后通过主线程回调,设置到目标 ImageView

结尾讲讲load中的两种查找优化方式

内存缓存(LRU):使用LinkedHashMap,它除了维护键值对的哈希表结构外,还维护了一个双向链表来记录元素的插入顺序或访问顺序,当 accessOrder 设置为 true 时,LinkedHashMap 会按照访问顺序来维护链表:每当一个元素被访问(get()put()),它就会被移动到链表的尾部,这样头部永远存储访问次数最少的元素,当超过维护的最大容量时,就会从头部移除元素

磁盘缓存(DiskLRU):指定一个目录进行存储,通过访问时间维护判断哪些是最近最少使用的,当在空间不足时进行淘汰

先通过内存缓存查找,若未找到再通过磁盘缓存查找,最后通过网络请求访问

谢谢看到这里,Glide雀食好用