glide:3.7.0 使用
引入
compile 'com.github.bumptech.glide:glide:3.7.0'
混淆
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public class * extends com.bumptech.glide.module.AppGlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
**[] $VALUES;
public *;
}
# for DexGuard only
-keepresourcexmlelements manifest/application/meta-data@value=GlideModule
使用
使用的方式十分简单,和Picasso差不多
Glide.with(this).load("https://timgsa.baidu.com/timg?image&quality=80&size=b10000_10000&sec=1511148367&di=f2289ba7ce873fddd5e85dab9410ebeb&src=http%3A%2F%2Fi-1.yxdown.com%2F2013%2F11%2F6%2F94ba6d62-7676-4ced-abe0-0c6a279369f4.jpg")
.placeholder(R.drawable.ic_launcher_background)
.into(mIv);
同样也可以为他设置其他,例如 listener 、 centerCrop 、transform 、 sizeMultiplier
.listener(new RequestListener() {
@Override
public boolean onException(Exception e, String model, Target target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(GlideDrawable resource, String model, Target target, boolean isFromMemoryCache, boolean isFirstResource) {
return false;
}
})
.centerCrop()
....
之类的,这些使用的方法和Picasso十分类似。
源码分析
RequestManager
Glide.with(context)
从 Glide.with 开始分析起。
public static RequestManager with(FragmentActivity activity) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(activity);
}
先看看 RequestManagerRetriever.get() 方法都干了什么
private static final RequestManagerRetriever INSTANCE = new RequestManagerRetriever();
RequestManagerRetriever() {
handler = new Handler(Looper.getMainLooper(), this /* Callback */);
}
上述的方其实就是 拿取了 RequestManagerRetriever 的单例对象。而这 RequestManagerRetriever 的构造函数所做的就只有 初始化 一个 handler ,这个handler 最终回调到主线程。
然后看看 retriever.get(activity)
public RequestManager get(Activity activity) {
if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
return get(activity.getApplicationContext());
} else {
//判断activity是否已经是销毁状态
assertNotDestroyed(activity);
//获取FragmentManager 对象
FragmentManager fm = activity.getSupportFragmentManager();
//创建Fragment,RequestManager并将其绑定
return supportFragmentGet(activity, fm);
}
}
然后就 调用了 supportFragmentGet(activity, fm);
RequestManager supportFragmentGet(Context context, FragmentManager fm) {
// 注 1
SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm);
// 注 2
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
current.setRequestManager(requestManager);
}
return requestManager;
}
注 1 :
getSupportRequestManagerFragment 方法
SupportRequestManagerFragment getSupportRequestManagerFragment(final FragmentManager fm) {
SupportRequestManagerFragment current = (SupportRequestManagerFragment) fm.findFragmentByTag(
FRAGMENT_TAG);
// 判断是否能从 fm 里面拿到Tag为FRAGMENT_TAG的SupportRequestManagerFragment
if (current == null) {
//current 为空 那么就从 pendingSupportRequestManagerFragments 里面拿取。pendingSupportRequestManagerFragments 其实是一个Map ,根据 fm 来获取 这个 创建过的 SupportRequestManagerFragment。
current = pendingSupportRequestManagerFragments.get(fm);
//如果没有就创建一个 SupportRequestManagerFragment ,并把他放在 pendingSupportRequestManagerFragments 里面。
if (current == null) {
current = new SupportRequestManagerFragment();
pendingSupportRequestManagerFragments.put(fm, current);
// 添加标记
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
那么就看看 创建 SupportRequestManagerFragment 都干了什么
public SupportRequestManagerFragment() {
this(new ActivityFragmentLifecycle());
}
@SuppressLint("ValidFragment")
public SupportRequestManagerFragment(ActivityFragmentLifecycle lifecycle) {
this.lifecycle = lifecycle;
}
他会生成初始化一个 ActivityFragmentLifecycle 对象 。这个对象用于管理 Activity、Fragment 的生命周期的状态。而在SupportRequestManagerFragment类里面,我们可以看到有如下代码:
@Override
public void onStop() {
super.onStop();
lifecycle.onStop();
}
@Override
public void onDestroy() {
super.onDestroy();
lifecycle.onDestroy();
}
他会和生命周期关联上。而生命周期的状态全部交给了 ActivityFragmentLifecycle 这个类来实现。
注 2 :
从 SupportRequestManagerFragment 里面获取 RequestManager 。 很明显 ,初始化的时候并没有创建 RequestManager 对象 ,那么就创建一个新的 RequestManager 对象 ,并设置给 SupportRequestManagerFragment 对象。
requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
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;
//获取 Glide 实例 ,这又是一个单例对象
this.glide = Glide.get(context);
this.optionsApplier = new OptionsApplier();
....
}
新创建的 RequestManager 也绑定了 生命周期。
DrawableTypeRequest
那么 RequestManager 对象得以生成。 接下来我们最常的操作就是使用 load 方法 创建DrawableTypeRequest 对象了。
DrawableTypeRequest load = with.load("https://timgsa.baidu.com/timg?image&quality=80&size=b10000_10000&sec=1511148367&di=f2289ba7ce873fddd5e85dab9410ebeb&src=http%3A%2F%2Fi-1.yxdown.com%2F2013%2F11%2F6%2F94ba6d62-7676-4ced-abe0-0c6a279369f4.jpg");
RequestManager 类 里面的 load 方法
load 实现了很多个重载 load(byte[] model) 、load(String string) ..... ,所以会根据不同的参数来返回不同的 DrawableTypeRequest
public DrawableTypeRequest load(byte[] model) {
return (DrawableTypeRequest) fromBytes().load(model);
}
public DrawableTypeRequest load(String string) {
return (DrawableTypeRequest) fromString().load(string);
}
不同的参数 , 就会执行不同的方法来生成 DrawableTypeRequest 对象 ,然后执行 load 方法 。
DrawableRequestBuilder.java
public DrawableRequestBuilder load(ModelType model) {
// 交给父类处理
super.load(model);
return this;
}
GenericRequestBuilder.java
public GenericRequestBuilder load(ModelType model) {
// model 赋值
this.model = model;
isModelSet = true;
return this;
}
那么最后就生成了 DrawableTypeRequest 对象。利用这个对象我们可以设置 placeholder 、 listener 、error ...等
@Override
public DrawableRequestBuilder placeholder(Drawable drawable) {
super.placeholder(drawable);
return this;
}
@Override
public DrawableRequestBuilder listener(
RequestListener super ModelType, GlideDrawable> requestListener) {
super.listener(requestListener);
return this;
}
@Override
public DrawableRequestBuilder error(Drawable drawable) {
super.error(drawable);
return this;
}
最后查看父类的代码,可以知道设置这些属性都是为 GenericRequestBuilder 的属性赋值。
public GenericRequestBuilder placeholder(
Drawable drawable) {
//为 placeholderDrawable 赋值
this.placeholderDrawable = drawable;
return this;
}
public GenericRequestBuilder listener(
RequestListener super ModelType, TranscodeType> requestListener) {
//为 requestListener 赋值
this.requestListener = requestListener;
return this;
}
public GenericRequestBuilder error(
Drawable drawable) {
//为 errorPlaceholder 赋值
this.errorPlaceholder = drawable;
return this;
}
into
为 GenericRequestBuilder 的属性设置的差不多了 ,那么最后所要调用的 就是 into 这个方法。
DrawableRequestBuilder.java
@Override
public Target into(ImageView view) {
return super.into(view);
}
GenericRequestBuilder.java
public Target into(ImageView view) {
Util.assertMainThread();
if (view == null) {
throw new IllegalArgumentException("You must pass in a non null View");
}
if (!isTransformationSet && view.getScaleType() != null) {
switch (view.getScaleType()) {
case CENTER_CROP:
applyCenterCrop();
break;
case FIT_CENTER:
case FIT_START:
case FIT_END:
applyFitCenter();
break;
//$CASES-OMITTED$
default:
// Do nothing.
}
}
return into(glide.buildImageViewTarget(view, transcodeClass));
}
最后实际调用到这个方法里面
public > Y into(Y target) {
// 判断是否在主线程 , 如果不在主线程那么就抛出异常
Util.assertMainThread();
.....
//获取之前的请求
Request previous = target.getRequest();
// requestTracker是请求跟踪类对象,主要管理请求的发起,暂停,清除
// 如果之前的请求已存在 ,那么就清空这个,并从 requestTracker 移除
if (previous != null) {
previous.clear();
requestTracker.removeRequest(previous);
previous.recycle();
}
//建立新的 请求
Request request = buildRequest(target);
// 设置 target 的request
target.setRequest(request);
//将target加入lifecycle
lifecycle.addListener(target);
//执行请求
requestTracker.runRequest(request);
return target;
}
buildRequest 创建请求
先看看 创建请求 吧
private Request buildRequest(Target target) {
if (priority == null) {
priority = Priority.NORMAL;
}
return buildRequestRecursive(target, null);
}
private Request buildRequestRecursive(Target target, ThumbnailRequestCoordinator parentCoordinator) {
if (thumbnailRequestBuilder != null) {
....
// ①
ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
Request fullRequest = obtainRequest(target, sizeMultiplier, priority, coordinator);
isThumbnailBuilt = true;
Request thumbRequest = thumbnailRequestBuilder.buildRequestRecursive(target, coordinator);
isThumbnailBuilt = false;
coordinator.setRequests(fullRequest, thumbRequest);
return coordinator;
} else if (thumbSizeMultiplier != null) { // ②
ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
Request fullRequest = obtainRequest(target, sizeMultiplier, priority, coordinator);
Request thumbnailRequest = obtainRequest(target, thumbSizeMultiplier, getThumbnailPriority(), coordinator);
coordinator.setRequests(fullRequest, thumbnailRequest);
return coordinator;
} else { // ③
return obtainRequest(target, sizeMultiplier, priority, parentCoordinator);
}
}
根据 DrawableTypeRequest 的设置 ,如果对 DrawableTypeRequest 对象调用了 thumbnail 方法 ,那么就会执行 ① 或 ② ,否则执行 ③
private Request obtainRequest(Target target, float sizeMultiplier, Priority priority,
RequestCoordinator requestCoordinator) {
return GenericRequest.obtain(
loadProvider,
model,
signature,
context,
priority,
target,
sizeMultiplier,
placeholderDrawable,
placeholderId,
errorPlaceholder,
errorId,
fallbackDrawable,
fallbackResource,
requestListener,
requestCoordinator,
glide.getEngine(),
transformation,
transcodeClass,
isCacheable,
animationFactory,
overrideWidth,
overrideHeight,
diskCacheStrategy);
}
GenericRequest.java
public static GenericRequest obtain(
参数 .....
DiskCacheStrategy diskCacheStrategy) {
@SuppressWarnings("unchecked")
GenericRequest request = (GenericRequest) REQUEST_POOL.poll();
if (request == null) {
request = new GenericRequest();
}
//初始化 request
request.init(loadProvider,
参数 ....
diskCacheStrategy);
return request;
}
runRequest 执行请求
public void runRequest(Request request) {
//将request对象添加到请求集合中
requests.add(request);
//如果当前状态是非暂停的,调用begin方法发送请求
if (!isPaused) {
request.begin();
} else {
//将请求添加到挂起的请求集合
pendingRequests.add(request);
}
}
GenericRequest.java
@Override
public void begin() {
startTime = LogTime.getLogTime();
if (model == null) {
// 加载错误
onException(null);
return;
}
status = Status.WAITING_FOR_SIZE;
// 验证宽高是否合法
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
// 注 1
onSizeReady(overrideWidth, overrideHeight);
} else {
target.getSize(this);
}
//设置加载前的默认图片(placeholder)
if (!isComplete() && !isFailed() && canNotifyStatusChanged()) {
target.onLoadStarted(getPlaceholderDrawable());
}
....
}
注 1
public void onSizeReady(int width, int height) {
....
if (status != Status.WAITING_FOR_SIZE) {
return;
}
// 将请求状态更新为运行状态
status = Status.RUNNING;
//根据 DrawableRequestBuilder 类的 sizeMultiplier 方法设置的 izeMultiplier
width = Math.round(sizeMultiplier * width);
height = Math.round(sizeMultiplier * height);
....
loadedFromMemoryCache = true;
// 注 1
loadStatus = engine.load(signature, width, height, dataFetcher, loadProvider, transformation, transcoder,
priority, isMemoryCacheable, diskCacheStrategy, this);
loadedFromMemoryCache = resource != null;
...
}
注 1 : 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();
// 创建 EngineKey 对象
EngineKey key = keyFactory.buildKey(id, signature, width, height, loadProvider.getCacheDecoder(),
loadProvider.getSourceDecoder(), transformation, loadProvider.getEncoder(),
transcoder, loadProvider.getSourceEncoder());
// 从内存缓存中查找
EngineResource> cached = loadFromCache(key, isMemoryCacheable);
if (cached != null) {
//缓存中存在,则回调 onResourceReady
cb.onResourceReady(cached);
...
return null;
}
// 尝试从活动Resources 中获取,它表示的是当前正在使用的Resources,与内存缓存不同之处是clear缓存时不会clear它。
EngineResource> active = loadFromActiveResources(key, isMemoryCacheable);
if (active != null) {
//存在,则回调 onResourceReady
cb.onResourceReady(active);
...
return null;
}
// 从 jobs 中获取是不是已经存在了这个任务,如果current != null ,那么之前已经提交了这个任务
EngineJob current = jobs.get(key);
if (current != null) {
//为这个任务增加回调
current.addCallback(cb);
....
return new LoadStatus(cb, current);
}
// 缓存中没有,也没有提交过任务,那么就创建新的 EngineJob
EngineJob engineJob = engineJobFactory.build(key, isMemoryCacheable);
DecodeJob decodeJob = new DecodeJob(key, width, height, fetcher, loadProvider, transformation,
transcoder, diskCacheProvider, diskCacheStrategy, priority);
//创建一个 EngineRunnable 。这个是任务执行的入口 ,实现了 Runnable 接口
EngineRunnable runnable = new EngineRunnable(engineJob, decodeJob, priority);
// 加入 jobs
jobs.put(key, engineJob);
engineJob.addCallback(cb);
//任务开始
engineJob.start(runnable);
.....
return new LoadStatus(cb, engineJob);
}
任务 开始 : engineJob.start(runnable);
public void start(EngineRunnable engineRunnable) {
this.engineRunnable = engineRunnable;
// diskCacheService 是线程池 , 那么就把 runable 提交给线程池了
future = diskCacheService.submit(engineRunnable);
}
那么就看看 engineRunnable 的 run 方法都实现了什么吧
@Override
public void run() {
if (isCancelled) {
return;
}
Exception exception = null;
Resource> resource = null;
try {
// 注 1
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);
}
}
注 1
decode 方法就用来获取资源了
private Resource> decode() throws Exception {
if (isDecodingFromCache()) {
// 从缓存中获取数据
return decodeFromCache();
} else {
//从其他途径获取资源 (网络、file等)
return decodeFromSource();
}
}
decodeFromCache() 从缓存中获取数据
private Resource> decodeFromCache() throws Exception {
Resource> result = null;
try {
result = decodeJob.decodeResultFromCache();
} catch (Exception e) {
....
}
if (result == null) {
result = decodeJob.decodeSourceFromCache();
}
return result;
}
那么就看看 decodeJob.decodeResultFromCache(); 里面干了什么
public Resource decodeResultFromCache() throws Exception {
if (!diskCacheStrategy.cacheResult()) {
return null;
}
long startTime = LogTime.getLogTime();
//继续调用了 loadFromCache
Resource transformed = loadFromCache(resultKey);
...
startTime = LogTime.getLogTime();
Resource result = transcode(transformed);
...
return result;
}
private Resource loadFromCache(Key key) throws IOException {
// 根据key从DiskCache获取文件
File cacheFile = diskCacheProvider.getDiskCache().get(key);
if (cacheFile == null) {
return null;
}
Resource result = null;
try {
// 把缓存文件读取解码生成Resource
result = loadProvider.getCacheDecoder().decode(cacheFile, width, height);
} finally {
if (result == null) {
diskCacheProvider.getDiskCache().delete(key);
}
}
return result;
}
decodeFromSource 从其他途径获取资源 (网络、file等)
private Resource> decodeFromSource() throws Exception {
//还是调用了decodeJob来获取与解码数据
return decodeJob.decodeFromSource();
}
DecodeJob.java
public Resource decodeFromSource() throws Exception {
Resource decoded = decodeSource();
return transformEncodeAndTranscode(decoded);
}
private Resource decodeSource() throws Exception {
Resource decoded = null;
try {
long startTime = LogTime.getLogTime();
// 注 1
final A data = fetcher.loadData(priority);
....
if (isCancelled) {
return null;
}
decoded = decodeFromSourceData(data);
} finally {
fetcher.cleanup();
}
return decoded;
}
读取数据
fetcher.loadData(priority);
fetcher 是 DataFetcher 接口 ,实现 DataFetcher 的接口 就可以改变数据获取的方式(网络、文件) 或者 途径(OkHttp,Volley) 了 。我们以原有的 HttpUrlFetcher 来分析。
HttpUrlFetcher.java
@Override
public InputStream loadData(Priority priority) throws Exception {
return loadDataWithRedirects(glideUrl.toURL(), 0 /*redirects*/, null /*lastUrl*/, glideUrl.getHeaders());
}
private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl, Map headers)
throws IOException {
.....
// 工厂创建 HttpURLConnection 对象
urlConnection = connectionFactory.build(url);
for (Map.Entry headerEntry : headers.entrySet()) {
urlConnection.addRequestProperty(headerEntry.getKey(), headerEntry.getValue());
}
// 设置 网络连接参数
urlConnection.setConnectTimeout(2500);
urlConnection.setReadTimeout(2500);
urlConnection.setUseCaches(false); // 不使用网络缓存
urlConnection.setDoInput(true);
urlConnection.connect();
if (isCancelled) {
return null;
}
final int statusCode = urlConnection.getResponseCode();
if (statusCode / 100 == 2) {
// 请求成功
return getStreamForSuccessfulRequest(urlConnection);
} else {
...... 其他状态码判断
}
}
gilde 的网络请求用到了 HttpURLConnection ,我么可以自定义 DataFetcher ,实现 DataFetcher 接口 ,从而使用其他库进行网络请求 ,如OkHttp,Volley。
加载完图片后自然就是进行缓存,留给下一次请求使用。省略缓存分析......
接下来就是回调显示
那么 回到 engineRunnable 里面的 run 方法
@Override
public void run() {
...
resource = decode();
...
if (resource == null) {
onLoadFailed(exception);
} else {
onLoadComplete(resource);
}
}
成功就调用 onLoadComplete ,失败就调用 onLoadFailed 。
private void onLoadComplete(Resource resource) {
manager.onResourceReady(resource);
}
EngineJob.java
@Override
public void onResourceReady(final Resource> resource) {
this.resource = resource;
MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();
}
上面会发送一条 Message ,随后的操作就会回到了主线程处理。
接受消息
private static class MainThreadCallback implements Handler.Callback {
@Override
public boolean handleMessage(Message message) {
if (MSG_COMPLETE == message.what || MSG_EXCEPTION == message.what) {
EngineJob job = (EngineJob) message.obj;
if (MSG_COMPLETE == message.what) {
job.handleResultOnMainThread();
} else {
job.handleExceptionOnMainThread();
}
return true;
}
return false;
}
}
private 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);
//注 1
for (ResourceCallback cb : cbs) {
if (!isInIgnoredCallbacks(cb)) {
engineResource.acquire();
cb.onResourceReady(engineResource);
}
}
// Our request is complete, so we can release the resource.
engineResource.release();
}
注 1 :
方法中通过一个循环,调用了所有ResourceCallback的 onResourceReady()方法。
而 onResourceReady() 方法最后的调用就会用于刷新相对应的UI。