我是靠谱客的博主 灵巧翅膀,最近开发中收集的这篇文章主要介绍glide源码中包含了那种设计模式_简析Glide源码,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

什么是Glide

An image loading and caching library for Android focused on smooth scrolling

一个使得Android图片列表滑动时更加流畅的图片加载和缓存库。

Glide 优点

(1) Glide 不仅是支持图片缓存和加载,它支持 Gif、WebP、缩略图、Video

(2) 支持优先级处理

(3) 与 Activity/Fragment 生命周期一致,支持 trimMemory

(4) 支持 okhttp、Volley

(5) 与其它图片加载框架相比内存优化更良好

如何使用

Glide.with(this)

.load("http://t.cn/RJqUUdJ")

.placeholder( R.drawable.default )

.error( R.drawable.error)

.into(imageView);

Glide总体设计图

基本概念

RequestManager:请求管理,每一个Activity都会创建一个RequestManager,根据对应Activity的生命周期管理该Activity上所以的图片请求。

Engine:加载图片的引擎,根据Request创建EngineJob和DecodeJob。

EngineJob:图片加载。

DecodeJob:图片处理。

Glide 流程图

Glide 源码解析加载流程

1,Glide.with(初始化构建流程)

核心实现代码

/**

* Begin a load with Glide that will tied to the give {@link android.support.v4.app.FragmentActivity}'s lifecycle

* and that uses the given {@link android.support.v4.app.FragmentActivity}'s default options.

*

* @param activity The activity to use.

* @return A RequestManager for the given FragmentActivity that can be used to start a load.

*/

public static RequestManager with(FragmentActivity activity) {

RequestManagerRetriever retriever = RequestManagerRetriever.get();

return retriever.get(activity);

}

RequestManager supportFragmentGet(Context context, FragmentManager fm) {

SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm);

RequestManager requestManager = current.getRequestManager();

if (requestManager == null) {

requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());

current.setRequestManager(requestManager);

}

return requestManager;

}

RequestManager(Context context, final Lifecycle lifecycle, RequestManagerTreeNode treeNode,

RequestTracker requestTracker, ConnectivityMonitorFactory factory) {

this.context = context.getApplicationContext();

this.lifecycle = lifecycle;

this.treeNode = treeNode;

this.requestTracker = requestTracker;

this.glide = Glide.get(context);

this.optionsApplier = new OptionsApplier();

ConnectivityMonitor connectivityMonitor = factory.build(context,

new RequestManagerConnectivityListener(requestTracker));

// If we're the application level request manager, we may be created on a background thread. In that case we

// cannot risk synchronously pausing or resuming requests, so we hack around the issue by delaying adding

// ourselves as a lifecycle listener by posting to the main thread. This should be entirely safe.

if (Util.isOnBackgroundThread()) {

new Handler(Looper.getMainLooper()).post(new Runnable() {

@Override

public void run() {

lifecycle.addListener(RequestManager.this);

}

});

} else {

lifecycle.addListener(this);

}

lifecycle.addListener(connectivityMonitor);

}

/**

* Lifecycle callback that registers for connectivity events (if the android.permission.ACCESS_NETWORK_STATE

* permission is present) and restarts failed or paused requests.

*/

@Override

public void onStart() {

// onStart might not be called because this object may be created after the fragment/activity's onStart method.

resumeRequests();

}

/**

* Lifecycle callback that unregisters for connectivity events (if the android.permission.ACCESS_NETWORK_STATE

* permission is present) and pauses in progress loads.

*/

@Override

public void onStop() {

pauseRequests();

}

/**

* Lifecycle callback that cancels all in progress requests and clears and recycles resources for all completed

* requests.

*/

@Override

public void onDestroy() {

requestTracker.clearRequests();

}

2,Glide.load(调用后builder就创建好了。之后就可以通过builder模式来配置参数了。)

1,创建DrawableTypeRequest并利用它的load方法设置相关参数

public DrawableTypeRequest load(String string) {

return (DrawableTypeRequest) fromString().load(string);

}

public DrawableTypeRequest fromString() {

return loadGeneric(String.class);

}

2,装载对象(包含请求的发起点)

private DrawableTypeRequest loadGeneric(Class modelClass) {

ModelLoader streamModelLoader = Glide.buildStreamModelLoader(modelClass, context);

ModelLoader fileDescriptorModelLoader =

Glide.buildFileDescriptorModelLoader(modelClass, context);

if (modelClass != null && streamModelLoader == null && fileDescriptorModelLoader == null) {

throw new IllegalArgumentException("Unknown type " + modelClass + ". You must provide a Model of a type for"

+ " which there is a registered ModelLoader, if you are using a custom model, you must first call"

+ " Glide#register with a ModelLoaderFactory for your custom model class");

} //生成request

return optionsApplier.apply(

new DrawableTypeRequest(modelClass, streamModelLoader, fileDescriptorModelLoader, context,

glide, requestTracker, lifecycle, optionsApplier));

}

public static ModelLoader buildStreamModelLoader(Class modelClass, Context context) {

return buildModelLoader(modelClass, InputStream.class, context);

}

public static ModelLoader buildModelLoader(Class modelClass, Class resourceClass,

Context context) {

if (modelClass == null) {

if (Log.isLoggable(TAG, Log.DEBUG)) {

Log.d(TAG, "Unable to load null model, setting placeholder only");

}

return null;

}

return Glide.get(context).getLoaderFactory().buildModelLoader(modelClass, resourceClass);

}

public synchronized ModelLoader buildModelLoader(Class modelClass, Class resourceClass) {

ModelLoader result = getCachedLoader(modelClass, resourceClass);

if (result != null) {

// We've already tried to create a model loader and can't with the currently registered set of factories,

// but we can't use null to demonstrate that failure because model loaders that haven't been requested

// yet will be null in the cache. To avoid this, we use a special signal model loader.

if (NULL_MODEL_LOADER.equals(result)) {

return null;

} else {

return result;

}

}

final ModelLoaderFactory factory = getFactory(modelClass, resourceClass);

if (factory != null) {

result = factory.build(context, this);

cacheModelLoader(modelClass, resourceClass, result);

} else {

// We can't generate a model loader for the given arguments with the currently registered set of factories.

cacheNullLoader(modelClass, resourceClass);

}

return result;

}

private ModelLoader getCachedLoader(Class modelClass, Class resourceClass) {

Map resourceToLoaders = cachedModelLoaders.get(modelClass);

ModelLoader/*T, Y*/ result = null;

if (resourceToLoaders != null) {

result = resourceToLoaders.get(resourceClass);

}

return result;

}

/**

*/

public GenericRequestBuilder load(ModelType model) {

this.model = model;

isModelSet = true;

return this;

}

3,Glide.into(开始干活了,查找缓存,开始Job 加载图片,显示图片)

public > Y into(Y target) {

Util.assertMainThread();

if (target == null) {

throw new IllegalArgumentException("You must pass in a non null Target");

}

if (!isModelSet) {

throw new IllegalArgumentException("You must first set a model (try #load())");

}

Request previous = target.getRequest();

if (previous != null) {

previous.clear();

requestTracker.removeRequest(previous);

previous.recycle();

}

Request request = buildRequest(target);

target.setRequest(request);

lifecycle.addListener(target);

requestTracker.runRequest(request);

return target;

}

/**

* Starts tracking the given request.

*/

public void runRequest(Request request) {

requests.add(request); //添加内存缓存

if (!isPaused) {

request.begin();// 开始

} else {

pendingRequests.add(request);// 挂起请求

}

}

@Override

public void begin() {

startTime = LogTime.getLogTime();

if (model == null) {// 如果model空的,那么是不能执行的。

onException(null);

return;

}

status = Status.WAITING_FOR_SIZE;// View尺寸已经获取到了,进入开始加载

if (Util.isValidDimensions(overrideWidth, overrideHeight)) {

onSizeReady(overrideWidth, overrideHeight);

} else {

target.getSize(this);

}

if (!isComplete() && !isFailed() && canNotifyStatusChanged()) {

target.onLoadStarted(getPlaceholderDrawable());

}

if (Log.isLoggable(TAG, Log.VERBOSE)) {

logV("finished run method in " + LogTime.getElapsedMillis(startTime));

}

}

/**

*主要的作用就是发起load操作

*/

@Override

public void onSizeReady(int width, int height) {

if (Log.isLoggable(TAG, Log.VERBOSE)) {

logV("Got onSizeReady in " + LogTime.getElapsedMillis(startTime));

}

if (status != Status.WAITING_FOR_SIZE) {

return;

}

status = Status.RUNNING;

width = Math.round(sizeMultiplier * width);

height = Math.round(sizeMultiplier * height);

ModelLoader modelLoader = loadProvider.getModelLoader();

final DataFetcher dataFetcher = modelLoader.getResourceFetcher(model, width, height);

if (dataFetcher == null) {

onException(new Exception("Failed to load model: '" + model + "'"));

return;

}

ResourceTranscoder transcoder = loadProvider.getTranscoder();

if (Log.isLoggable(TAG, Log.VERBOSE)) {

logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime));

}//调用engine 开始加载

loadedFromMemoryCache = true;

loadStatus = engine.load(signature, width, height, dataFetcher, loadProvider, transformation, transcoder,

priority, isMemoryCacheable, diskCacheStrategy, this);

loadedFromMemoryCache = resource != null;

if (Log.isLoggable(TAG, Log.VERBOSE)) {

logV("finished onSizeReady in " + LogTime.getElapsedMillis(startTime));

}

}

/**Engine.load的详细过程:*/

public LoadStatus load(Key signature, int width, int height, DataFetcher fetcher,

DataLoadProvider loadProvider, Transformation transformation, ResourceTranscoder transcoder,

Priority priority, boolean isMemoryCacheable, DiskCacheStrategy diskCacheStrategy, ResourceCallback cb) {

Util.assertMainThread();

long startTime = LogTime.getLogTime();

final String id = fetcher.getId();// 创建key,唯一标示加载资源。

EngineKey key = keyFactory.buildKey(id, signature, width, height, loadProvider.getCacheDecoder(),//通过key查找缓存资源

loadProvider.getSourceDecoder(), transformation, loadProvider.getEncoder(),

transcoder, loadProvider.getSourceEncoder());

EngineResource> 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;

}

EngineResource> active = loadFromActiveResources(key, isMemoryCacheable);//查找二级缓存是否有job

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);//获取缓存的job

if (current != null) {

current.addCallback(cb);

if (Log.isLoggable(TAG, Log.VERBOSE)) {

logWithTimeAndKey("Added to existing load", startTime, key);

}

return new LoadStatus(cb, current);

}

EngineJob engineJob = engineJobFactory.build(key, isMemoryCacheable);//创建job

DecodeJob decodeJob = new DecodeJob(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);

}

内存缓存:在Glide中默认是LruResourceCache。当然你也可以自定义;

两级内存缓存(loadFromActiveResources)。一级缓存采用LRU算法进行缓存,并不能保证全部能命中,添加二级缓存提高命中率之用;

EngineJob和DecodeJob各自职责:EngineJob充当了管理和调度者,主要负责加载和各类回调通知;DecodeJob是真正干活的劳动者,这个类实现了Runnable接口。

下面来看看DecodeJob是如何执行的:

@Override

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 decodeSource() throws Exception {

Resource 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;

}

decoded = decodeFromSourceData(data);

} finally {

fetcher.cleanup();

}

return decoded;

}

private Resource decodeFromSourceData(A data) throws IOException {

final Resource decoded;

if (diskCacheStrategy.cacheSource()) {

decoded = cacheAndDecodeSourceData(data);

} else {

long startTime = LogTime.getLogTime();

decoded = loadProvider.getSourceDecoder().decode(data, width, height);

if (Log.isLoggable(TAG, Log.VERBOSE)) {

logWithTimeAndKey("Decoded from source", startTime);

}

}

return decoded;

}

private void onLoadComplete(Resource resource) {

manager.onResourceReady(resource);

}

@Override

public void onResourceReady(final Resource> resource) {

this.resource = resource;

MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();

}

总结

Glide的扩展性非常高,并且支持对处理后的资源Disk缓存,通过BitmapPool对实现了对Bitmap复用,使用activityResources缓存正在使用的resource,对于BitmapPool饱和移除的Bitmap直接调用recycle加速内存回收,通过RequestManager实现了监听LifeRecycle来对图片加载任务的及时回收。

最后

以上就是灵巧翅膀为你收集整理的glide源码中包含了那种设计模式_简析Glide源码的全部内容,希望文章能够帮你解决glide源码中包含了那种设计模式_简析Glide源码所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部