源码阅读--Glide
来源:互联网 发布:vb wince 全屏 编辑:程序博客网 时间:2024/06/05 04:40
1.用法及参考资料
参考资料:http://www.apkbus.com/blog-705730-60158.html
用法:
Glide.with(this).load("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1494417111222&di=0679f94eacd58059affec7cc9a33c731&imgtype=0&src=http%3A%2F%2Fi.zeze.com%2Fattachment%2Fforum%2F201506%2F28%2F104039ydramgzhbzxarof9.jpg").into(mImageView;
2.重要类的说明
(1)Engine
负责任务创建,发起,回调,资源的管理
public <R> LoadStatus load(/** */) { ...... EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);//----------------------------WeakReference ...... EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable); //------------------------------------Map<Key, WeakReference<EngineResource<?>>> activeResources,从这个参数里面获取的 //--------------------------------------activeResources在构造函数中赋值,在loadFromCache中添加(如果cache中有的话) ...... //---------------------------------------------------------------获取相关联的EngineJob EngineJob<?> current = jobs.get(key);//-----------------------------jobs是一个Map<Key, EngineJob<?>>,在构造函数中被赋值 if (current != null) {//--------------------------------成功获取,添加Callback current.addCallback(cb); if (Log.isLoggable(TAG, Log.VERBOSE)) { logWithTimeAndKey("Added to existing load", startTime, key); } return new LoadStatus(cb, current); } //-------------------------------------------------------相关联的EngineJob获取失败 EngineJob<R> engineJob = engineJobFactory.build(key, isMemoryCacheable, useUnlimitedSourceExecutorPool); DecodeJob<R> decodeJob = decodeJobFactory.build(/....../); jobs.put(key, engineJob); engineJob.addCallback(cb); engineJob.start(decodeJob);//---------------------------------发起新的decodeJob return new LoadStatus(cb, engineJob); }
(2)EngineJob
调度 DecodeJob,添加,移除资源回调,并 notify 回调
如果从cache中获取,那就由diskCacheExecutor来执行decodeJob,否则由ActiveSourceExecutor来执行
public void start(DecodeJob<R> decodeJob) { this.decodeJob = decodeJob; GlideExecutor executor = decodeJob.willDecodeFromCache() ? diskCacheExecutor : getActiveSourceExecutor(); executor.execute(decodeJob); }
(3)DecodeJob
实现了 Runnable 接口,调度任务的核心类,整个请求的繁重工作都在这里完成:处理来自缓存或者原始的资源,应用转换动画以及 transcode
run方法里面调用了runWrapped
private void runWrapped() { switch (runReason) { case INITIALIZE: stage = getNextStage(Stage.INITIALIZE);//-----------------------获取Stage(INITIALIZE,RESOURCE_CACHE,DATA_CACHE,SOURCE,ENCODE,FINISHED) currentGenerator = getNextGenerator();//-----------------------根据Stage获取对应的CacheGenerator runGenerators(); break; case SWITCH_TO_SOURCE_SERVICE: runGenerators(); break; case DECODE_DATA: decodeFromRetrievedData();//---------------------------调用decodeFromData,如果失败也会调用runGenerators break; } }
runGenerators内部会调用reschedule,重新调度
public void reschedule(DecodeJob<?> job) { if (isCancelled) { MAIN_THREAD_HANDLER.obtainMessage(MSG_CANCELLED, this).sendToTarget(); } else { getActiveSourceExecutor().execute(job); } }
3.用法解析
(1)with函数
public static RequestManager with(FragmentActivity activity) { return getRetriever(activity).get(activity); }
getRetriever获取的是一个RequestManagerRetriever
private static RequestManagerRetriever getRetriever(@Nullable Context context) { 。。。。。。 return Glide.get(context).getRequestManagerRetriever();//-----------------------get函数中有对Glide的初始化initGlide } private static void initGlide(Context context) { 。。。。。。 RequestManagerRetriever.RequestManagerFactory factory = annotationGeneratedModule != null ? annotationGeneratedModule.getRequestManagerFactory() : null; GlideBuilder builder = new GlideBuilder().setRequestManagerFactory(factory); 。。。。。。 glide = builder.build(applicationContext);//-----------------------------建造者模式生成glide 。。。。。。 }
再来看一下getRetriever之后的get函数做了什么
public RequestManager get(FragmentActivity activity) { if (Util.isOnBackgroundThread()) { return get(activity.getApplicationContext()); } else { assertNotDestroyed(activity); FragmentManager fm = activity.getSupportFragmentManager(); return supportFragmentGet(activity, fm, null /*parentHint*/); } } public RequestManager get(Context context) { 。。。。。。 return getApplicationManager(context); } private RequestManager getApplicationManager(Context context) { if (applicationManager == null) { synchronized (this) { if (applicationManager == null) { 。。。。。。 Glide glide = Glide.get(context); applicationManager = factory.build(glide, new ApplicationLifecycle(), new EmptyRequestManagerTreeNode()); } } } return applicationManager; }
applicationManager就是RequestManager
上面是isOnBackgroundThread,那么就是在主线程的流程————-说白了也就是为了获得RequestManager
private RequestManager supportFragmentGet(Context context, FragmentManager fm, Fragment parentHint) { SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint); RequestManager requestManager = current.getRequestManager(); if (requestManager == null) { // TODO(b/27524013): Factor out this Glide.get() call. Glide glide = Glide.get(context); requestManager = factory.build(glide, current.getLifecycle(), current.getRequestManagerTreeNode()); current.setRequestManager(requestManager); } return requestManager; }
综上,整个with函数就为了获得RequestManager。
它里面有个RequestTracker是用来保存request的,用的是WeakHashMap
//----------------------------------------------删除不再正常使用的entry private void expungeStaleEntries() { for (Object x; (x = queue.poll()) != null; ) {//-------------------------------这里的queue是ReferenceQueue(Reference queue for cleared WeakEntries) synchronized (queue) { Entry<K,V> e = (Entry<K,V>) x; int i = indexFor(e.hash, table.length); Entry<K,V> prev = table[i]; Entry<K,V> p = prev; while (p != null) { Entry<K,V> next = p.next; if (p == e) { if (prev == e) table[i] = next; else prev.next = next; // Must not null out e.next; // stale entries may be in use by a HashIterator e.value = null; // Help GC size--; break; } prev = p; p = next; } } } }
这个“弱键”的原理呢?大致上就是,通过WeakReference和ReferenceQueue实现的。 WeakHashMap的key是“弱键”,即是WeakReference类型的;ReferenceQueue是一个队列,它会保存被GC回收的“弱键”。实现步骤是:
(01) 新建WeakHashMap,将“键值对”添加到WeakHashMap中。实际上,WeakHashMap是通过数组table保存Entry(键值对);每一个Entry实际上是一个单向链表,即Entry是键值对链表。
(02) 当某“弱键”不再被其它对象引用,并被GC回收时。在GC回收该“弱键”时,这个“弱键”也同时会被添加到ReferenceQueue(queue)队列中。
(03) 当下一次我们需要操作WeakHashMap时,会先同步table和queue。table中保存了全部的键值对,而queue中保存被GC回收的键值对;同步它们,就是删除table中被GC回收的键值对。
这就是“弱键”如何被自动从WeakHashMap中删除的步骤了。
(2)load函数
跟踪进去就是配置了点参数
(3)into函数
public <Y extends Target<TranscodeType>> Y into(@NonNull Y target) { Util.assertMainThread(); Preconditions.checkNotNull(target); if (!isModelSet) { throw new IllegalArgumentException("You must call #load() before calling #into()"); } Request previous = target.getRequest(); if (previous != null) { requestManager.clear(target); } requestOptions.lock(); Request request = buildRequest(target); target.setRequest(request); requestManager.track(target, request);//-----------------------获取了Request以后就开始runRequest------request.begin(); return target; } @Override public void begin() { ...... status = Status.WAITING_FOR_SIZE; if (Util.isValidDimensions(overrideWidth, overrideHeight)) { onSizeReady(overrideWidth, overrideHeight);//----------------------------------------获取数据并解析 } else { target.getSize(this); } if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE) && canNotifyStatusChanged()) { target.onLoadStarted(getPlaceholderDrawable());//------------------------------------把图片加载进控件中 } if (Log.isLoggable(TAG, Log.VERBOSE)) { logV("finished run method in " + LogTime.getElapsedMillis(startTime)); } } public void onSizeReady(int width, int height) { 。。。。。。 status = Status.RUNNING; float sizeMultiplier = requestOptions.getSizeMultiplier(); this.width = maybeApplySizeMultiplier(width, sizeMultiplier); this.height = maybeApplySizeMultiplier(height, sizeMultiplier); loadStatus = engine.load(/*****/);//------------------------------------------之前讨论过的engine.load方法 。。。。。。 }
- Glide源码阅读一
- 源码阅读--Glide
- Glide源码
- Glide 源码解析
- Android Glide源码解析
- Android Glide源码解析
- Glide 源码解析
- glide源码分析
- Glide 源码解析
- Glide源码之生命周期
- Glide 源码分析
- Android Glide源码解析
- Android Glide源码解析
- glide源码编译
- Glide源码解析
- Glide源码解析
- Glide源码分析 一
- 《glide源码学习》
- 开源跨平台开发框架 [记录][U01]
- c/c++ sort函数、qsort函数使用
- Java面试宝典
- 一、数组的封装
- Maven 将本地jar加入maven仓库
- 源码阅读--Glide
- TCP数据流—滑动窗口,拥塞窗口,慢启动,Nagle算法,经受时延的确认等
- Centos6.5使用yum安装mysql
- 记录stdint.h头文件
- Java多线程学习
- 基于vs2008编译Tesseract 3.02.02
- 去除idea中xml黄色背景
- 2017第八届蓝桥杯C/C++ B组省赛题解(上)
- iOS: UILabel的adjustsFontSizeToFitWidth与 sizeToFit与sizeThatFits