前言
近期研究了一下Glide的图片加载框架,在这里和大家分享一下。由于代码研读有限,难免有错误的地方,了解的童鞋还望指正。学习小组QQ群: 193765960。
本篇是Glide框架及源码解析的第四篇,更多文章敬请关注后续文章。如果这篇文章对大家学习Glide有帮助,还望大家多多转载。
版权归作者所有,如有转发,请注明文章出处:https://xiaodanchen.github.io/archives/
相关文章:
跟着源码学设计:Glide框架及源码解析(一)
跟着源码学设计:Glide框架及源码解析(二)
跟着源码学设计:Glide框架及源码解析(三)
跟着源码学设计:Glide框架及源码解析(四)
跟着源码学设计:Glide框架及源码解析(五)
在之前的文章中,我们已经知道了Glide请求是如何被加载到请求队列中并执行的,也了解了资源是如何管理的。本篇文章我们将探究一下资源是如何获取并分发的。
资源请求和回调机制类图
request开启请求
request被加载到requestTracker中统一管理启动获取资源,代码如下:
- request的执行从其begin()方法开始:12345678public void runRequest(Request request) {requests.add(request);if (!isPaused) {request.begin();} else {pendingRequests.add(request);}}
获取Engin对象并封装任务
- 获取engine对象,在load()方法中创建EnginJob任务
- 为Enginjob创建异步线程EnginRunnable
- 为EnginRunnable初始化资源获取解析任务DecodJob123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566public <T, Z, R> LoadStatus load(Key signature, int width, int height, DataFetcher<T> fetcher,DataLoadProvider<T, Z> loadProvider, Transformation<Z> transformation, ResourceTranscoder<Z, R> transcoder,Priority priority, boolean isMemoryCacheable, DiskCacheStrategy diskCacheStrategy, ResourceCallback cb) {Util.assertMainThread();long startTime = LogTime.getLogTime();final String id = fetcher.getId();//获取keyEngineKey key = keyFactory.buildKey(id, signature, width, height, loadProvider.getCacheDecoder(),loadProvider.getSourceDecoder(), transformation, loadProvider.getEncoder(),transcoder, loadProvider.getSourceEncoder());//查找LruResourceCacheEngineResource<?> cached = loadFromCache(key, isMemoryCacheable);if (cached != null) {cb.onResourceReady(cached);if (Log.isLoggable(TAG, Log.VERBOSE)) {logWithTimeAndKey("Loaded resource from cache", startTime, key);}return null;}//查找ActiveResourceCacheEngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);if (active != null) {cb.onResourceReady(active);if (Log.isLoggable(TAG, Log.VERBOSE)) {logWithTimeAndKey("Loaded resource from active resources", startTime, key);}return null;}//任务排重EngineJob current = jobs.get(key);if (current != null) {current.addCallback(cb);if (Log.isLoggable(TAG, Log.VERBOSE)) {logWithTimeAndKey("Added to existing load", startTime, key);}return new LoadStatus(cb, current);}//创建EngineJobEngineJob engineJob = engineJobFactory.build(key, isMemoryCacheable);//创建DecodeJob:注意fetcher(数据加载器)DecodeJob<T, Z, R> decodeJob = new DecodeJob<T, Z, R>(key, width, height, fetcher, loadProvider, transformation,transcoder, diskCacheProvider, diskCacheStrategy, priority);//创建任务线程EngineRunnable runnable = new EngineRunnable(engineJob, decodeJob, priority);//将任务加入管理队列jobs.put(key, engineJob);engineJob.addCallback(cb);//启动任务engineJob.start(runnable);if (Log.isLoggable(TAG, Log.VERBOSE)) {logWithTimeAndKey("Started new load", startTime, key);}return new LoadStatus(cb, engineJob);}
执行任务获取数据并解析
DecodJob通过数据获取器DataFetcher获取数据文件(流)
request被加载到requestTracker中统一管理启动获取资源,代码如下:123456789101112131415161718192021222324252627282930313233343536373839404142//EngineRunnable的run()方法public void run() {if (isCancelled) {return;}Exception exception = null;Resource<?> resource = null;try {resource = decode();} catch (Exception e) {if (Log.isLoggable(TAG, Log.VERBOSE)) {Log.v(TAG, "Exception decoding", e);}exception = e;}if (isCancelled) {if (resource != null) {resource.recycle();}return;}if (resource == null) {onLoadFailed(exception);} else {onLoadComplete(resource);}}private Resource<?> decode() throws Exception {if (isDecodingFromCache()) {return decodeFromCache();} else {return decodeFromSource();}}private Resource<?> decodeFromSource() throws Exception {return decodeJob.decodeFromSource();}数据解析器对data数据解析生成resource资源对象
12345678910111213141516171819202122232425private Resource<T> decodeSource() throws Exception {Resource<T> decoded = null;try {long startTime = LogTime.getLogTime();//数据加载器获取数据final A data = fetcher.loadData(priority);if (Log.isLoggable(TAG, Log.VERBOSE)) {logWithTimeAndKey("Fetched data", startTime);}if (isCancelled) {return null;}//data数据解析生成resource资源对象decoded = decodeFromSourceData(data);} finally {fetcher.cleanup();}return decoded;}//HttpUrlFetcher:网络资源加载器public InputStream loadData(Priority priority) throws Exception {return loadDataWithRedirects(glideUrl.toURL(), 0 /*redirects*/, null /*lastUrl*/, glideUrl.getHeaders());}resource资源进一步封装成为EnginResource对象
12345678910//Runnable的方法,在run()方法中调用private void onLoadComplete(Resource resource) {manager.onResourceReady(resource);}//manager.onResourceReady(resource)实际回调了Enginjob的接口实现public void onResourceReady(final Resource<?> resource) {this.resource = resource;MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();}通过监听接口回传EnginResource对象
12345678910111213141516171819202122232425private void handleResultOnMainThread() {if (isCancelled) {resource.recycle();return;} else if (cbs.isEmpty()) {throw new IllegalStateException("Received a resource without any callbacks to notify");}engineResource = engineResourceFactory.build(resource, isCacheable);hasResource = true;// Hold on to resource for duration of request so we don't recycle it in the middle of notifying if it// synchronously released by one of the callbacks.engineResource.acquire();listener.onEngineJobComplete(key, engineResource);for (ResourceCallback cb : cbs) {if (!isInIgnoredCallbacks(cb)) {engineResource.acquire();//回传engineResource到request中,request获取到资源后开始刷新UIcb.onResourceReady(engineResource);}}// Our request is complete, so we can release the resource.engineResource.release();}
(本篇是Glide框架及源码解析的第四篇,更多文章敬请关注后续文章。版权归作者所有,如有转发,请注明文章出处:原文链接)