官方给出的简单使用的例子:
// For a simple view:
@Override public void onCreate(Bundle savedInstanceState) {
...
ImageView imageView = (ImageView) findViewById(R.id.my_image_view);
GlideApp.with(this).load("http://goo.gl/gEgYUd").into(imageView);
}
// For a simple image list:
@Override public View getView(int position, View recycled, ViewGroup container) {
final ImageView myImageView;
if (recycled == null) {
myImageView = (ImageView) inflater.inflate(R.layout.my_image_view, container, false);
} else {
myImageView = (ImageView) recycled;
}
String url = myUrls.get(position);
GlideApp
.with(myFragment)
.load(url)
.centerCrop()
.placeholder(R.drawable.loading_spinner)
.into(myImageView);
return myImageView;
}
其中最主要的就是部分就是:Glide.with(content).load(url).into(imageView)
首先来看with():
public static RequestManager with(Context context) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(context);
}
public static RequestManager with(Activity activity) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(activity);
}
public static RequestManager with(FragmentActivity activity) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(activity);
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static RequestManager with(android.app.Fragment fragment) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(fragment);
}
public static RequestManager with(Fragment fragment) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(fragment);
}
可以看到有五个重载方法,都调用了RequestManagerRetriever的get(),去获取一个RequestManagerRetriever的唯一实例:
/** The singleton instance of RequestManagerRetriever. */
// 单例模式中的饿汉式
private static final RequestManagerRetriever INSTANCE = new RequestManagerRetriever();
/**
* Retrieves and returns the RequestManagerRetriever singleton.
*/
public static RequestManagerRetriever get() {
return INSTANCE;
}
然后利用获取到的这个RequestManagerRetriever,调用get():
public RequestManager get(Context context) {
if (context == null) {
throw new IllegalArgumentException("You cannot start a load on a null Context");
} else if (Util.isOnMainThread() && !(context instanceof Application)) {
if (context instanceof FragmentActivity) {
return get((FragmentActivity) context);
} else if (context instanceof Activity) {
return get((Activity) context);
} else if (context instanceof ContextWrapper) {
return get(((ContextWrapper) context).getBaseContext());
}
}
return getApplicationManager(context);
}
public RequestManager get(FragmentActivity activity) {
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
FragmentManager fm = activity.getSupportFragmentManager();
return supportFragmentGet(activity, fm);
}
}
public RequestManager get(Fragment fragment) {
if (fragment.getActivity() == null) {
throw new IllegalArgumentException("You cannot start a load on a fragment before it is attached");
}
if (Util.isOnBackgroundThread()) {
return get(fragment.getActivity().getApplicationContext());
} else {
FragmentManager fm = fragment.getChildFragmentManager();
return supportFragmentGet(fragment.getActivity(), fm);
}
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public RequestManager get(Activity activity) {
if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
android.app.FragmentManager fm = activity.getFragmentManager();
return fragmentGet(activity, fm);
}
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public RequestManager get(android.app.Fragment fragment) {
if (fragment.getActivity() == null) {
throw new IllegalArgumentException("You cannot start a load on a fragment before it is attached");
}
if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
return get(fragment.getActivity().getApplicationContext());
} else {
android.app.FragmentManager fm = fragment.getChildFragmentManager();
return fragmentGet(fragment.getActivity(), fm);
}
}
同样是五个重载方法,我们来看其中一个:
// 这个fragment是v4包下的Fragment
public RequestManager get(Fragment fragment) {
if (fragment.getActivity() == null) {
// 判断fragment是否已经加添加到父容器上,如果没有抛出异常
throw new IllegalArgumentException("You cannot start a load on a fragment before it is attached");
}
if (Util.isOnBackgroundThread()) {
// 如果是在子线程中,返回一个由ApplicationContext构建的单例的RequestManager
return get(fragment.getActivity().getApplicationContext());
} else {
// 在主线程中的话,调用supportFragmentGet(),并且入参是当前fragment所在的Activity和FragmentManager
FragmentManager fm = fragment.getChildFragmentManager();
return supportFragmentGet(fragment.getActivity(), fm);
}
}
继续进入supportFragmentGet():
RequestManager supportFragmentGet(Context context, final FragmentManager fm) {
// 判断在当前的FragmentManager中是否已经加入了SupportRequestManagerFragment
SupportRequestManagerFragment current = (SupportRequestManagerFragment) fm.findFragmentByTag(TAG);
if (current == null) {
// 判断缓存中是否有该FragmentManager对应的SupportRequestManagerFragment
current = pendingSupportRequestManagerFragments.get(fm);
if (current == null) {
// 如果都没有,就创建一个SupportRequestManagerFragment,加入到当前的FragmentManager中
current = new SupportRequestManagerFragment();
pendingSupportRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current, TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
// 判断当前的FragmentManager是否有RequestManager
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
// 如果没有的话,创建一个RequestManager
requestManager = new RequestManager(context, current.getLifecycle());
current.setRequestManager(requestManager);
}
return requestManager;
}
这里我们来看一下SupportRequestManagerFragment究竟是什么:
public class SupportRequestManagerFragment extends Fragment {
private RequestManager requestManager;
private final ActivityFragmentLifecycle lifecycle;
public SupportRequestManagerFragment() {
this(new ActivityFragmentLifecycle());
}
// For testing only.
@SuppressLint("ValidFragment")
public SupportRequestManagerFragment(ActivityFragmentLifecycle lifecycle) {
this.lifecycle = lifecycle;
}
/**
* Sets the current {@link com.bumptech.glide.RequestManager}.
*
* @param requestManager The manager to set.
*/
public void setRequestManager(RequestManager requestManager) {
this.requestManager = requestManager;
}
ActivityFragmentLifecycle getLifecycle() {
return lifecycle;
}
/**
* Returns the current {@link com.bumptech.glide.RequestManager} or null if none is set.
*/
public RequestManager getRequestManager() {
return requestManager;
}
@Override
public void onStart() {
super.onStart();
lifecycle.onStart();
}
@Override
public void onStop() {
super.onStop();
lifecycle.onStop();
}
@Override
public void onDestroy() {
super.onDestroy();
lifecycle.onDestroy();
}
@Override
public void onLowMemory() {
super.onLowMemory();
// If an activity is re-created, onLowMemory may be called before a manager is ever set.
// See #329.
if (requestManager != null) {
requestManager.onLowMemory();
}
}
}
代码很简单,我们可以看出来SupportRequestManagerFragment创建的时候创建了一个ActivityFragmentLifecycle,用来回调SupportRequestManagerFragment的生命周期事件。
当父容器的生命周期改变的时候,我们当前的这个SupportRequestManagerFragment生命周期也会改变,然后就会回调ActivityFragmentLifecycle对应的方法。
回到上面requestManager = new RequestManager(context, current.getLifecycle());
,确实这里就把这个ActivityFragmentLifecycle作为构造函参数递到了RequestManager中。
至此,我们通过Glide.with()
获取了一个RequestManager对象。
load()也有很多重载:
public DrawableTypeRequest load(String string) {
return (DrawableTypeRequest) fromString().load(string);
}
public DrawableTypeRequest load(Uri uri) {
return (DrawableTypeRequest) fromUri().load(uri);
}
public DrawableTypeRequest load(File file) {
return (DrawableTypeRequest) fromFile().load(file);
}
public DrawableTypeRequest load(Integer resourceId) {
return (DrawableTypeRequest) fromResource().load(resourceId);
}
public DrawableTypeRequest load(URL url) {
return (DrawableTypeRequest) fromUrl().load(url);
}
public DrawableTypeRequest<byte[]> load(byte[] model) {
return (DrawableTypeRequest<byte[]>) fromBytes().load(model);
}
……
最终都创建了一个DrawableTypeRequest对象,接着进入into()。
/**
* Sets the {@link ImageView} the resource will be loaded into, cancels any existing loads into the view, and frees
* any resources Glide may have previously loaded into the view so they may be reused.
*
* @see Glide#clear(android.view.View)
*
* @param view The view to cancel previous loads for and load the new resource into.
* @return The {@link com.bumptech.glide.request.target.Target} used to wrap the given {@link ImageView}.
*/
public Target into(ImageView view) {
// 判断是否在主线程
Util.assertMainThread();
if (view == null) {
// 对ImageView判空
throw new IllegalArgumentException("You must pass in a non null View");
}
if (!isTransformationSet && view.getScaleType() != null) {
// 根据scaleType做一些处理
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));
}
进而调用into()的重载:
/**
* Set the target the resource will be loaded into.
*
* @see Glide#clear(com.bumptech.glide.request.target.Target)
*
* @param target The target to load the resource into.
* @return The given target.
*/
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) {
// 如果之前的请求不为空,则清除并且从requestTracker移除
previous.clear();
requestTracker.removeRequest(previous);
previous.recycle();
}
// 新建一个Request
Request request = buildRequest(target);
// 给该目标设置Request
target.setRequest(request);
// 将该目标加入生命周期的监听器集合中
lifecycle.addListener(target);
// 开始发起请求
requestTracker.runRequest(request);
return target;
}
接着进入runRequest():
/**
* Starts tracking the given request.
*/
// 开始追踪该请求
public void runRequest(Request request) {
requests.add(request);
if (!isPaused) {
// 非暂停状态,开始请求
request.begin();
} else {
// 否则加入暂停队列
pendingRequests.add(request);
}
}
进入begin():
public void begin() {
startTime = LogTime.getLogTime();
if (model == null) {
onException(null);
return;
}
// 修改状态
status = Status.WAITING_FOR_SIZE;
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
// 如果尺寸有效,进入onSizeReady()
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));
}
}
进入onSizeReady():
/**
* A callback method that should never be invoked directly.
*/
@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("Got null fetcher from model loader"));
return;
}
ResourceTranscoder transcoder = loadProvider.getTranscoder();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime));
}
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 <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();
// 生成一个EngineKey
EngineKey key = keyFactory.buildKey(id, signature, width, height, loadProvider.getCacheDecoder(),
loadProvider.getSourceDecoder(), transformation, loadProvider.getEncoder(),
transcoder, loadProvider.getSourceEncoder());
// 从内存缓存中获取EngineResource
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);
if (active != null) {
cb.onResourceReady(active);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Loaded resource from active resources", startTime, key);
}
return null;
}
// 获取Map中获取已经存在的改key对应的EngineJob
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);
}
// 如果以上都不满足,创建一个该key对应的EngineJob,它的作用是调度DecodeJob,添加,移除资源回调,并notify回调
EngineJob engineJob = engineJobFactory.build(key, isMemoryCacheable);
// 创建一个DecodeJob,处理来自缓存或者原始的资源,应用转换动画以及transcode。
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);
// 存储该EngineJob
jobs.put(key, engineJob);
engineJob.addCallback(cb);
// 开启EngineRunnable
engineJob.start(runnable);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Started new load", startTime, key);
}
// 返回一个LoadStatus,其中记录着EngineJob和一个ResourceCallback
return new LoadStatus(cb, engineJob);
}
进入start():
public void start(EngineRunnable engineRunnable) {
this.engineRunnable = engineRunnable;
// diskCacheService是一个线程池,默认的是一个先进先出同时有优先级的线程池FifoPriorityThreadPoolExecutor
future = diskCacheService.submit(engineRunnable);
}
线程池执行EngineRunnable,会调用EngineRunnable的run():
@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);
}
}
进入decode():
private Resource> decode() throws Exception {
if (isDecodingFromCache()) {
// 从缓存中获取
return decodeFromCache();
} else {
// 从真正的来源处获取
return decodeFromSource();
}
}
decodeFromSource()在一连串函数调用链之后会进入DecodeJob的decodeSource():
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;
}
进入DataFetcher的loadData(),根据来源的不同有不同的实现,我们这里看下HttpUrlFetcher,通过一个url获取资源:
@Override
public InputStream loadData(Priority priority) throws Exception {
return loadDataWithRedirects(glideUrl.toURL(), 0 /*redirects*/, null /*lastUrl*/);
}
private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl) throws IOException {
// 判断是否重定向的次数太多
if (redirects >= MAXIMUM_REDIRECTS) {
throw new IOException("Too many (> " + MAXIMUM_REDIRECTS + ") redirects!");
} else {
// Comparing the URLs using .equals performs additional network I/O and is generally broken.
// See http://michaelscharf.blogspot.com/2006/11/javaneturlequals-and-hashcode-make.html.
try {
if (lastUrl != null && url.toURI().equals(lastUrl.toURI())) {
throw new IOException("In re-direct loop");
}
} catch (URISyntaxException e) {
// Do nothing, this is best effort.
}
}
// 配置HttpURLConnection
urlConnection = connectionFactory.build(url);
urlConnection.setConnectTimeout(2500);
urlConnection.setReadTimeout(2500);
urlConnection.setUseCaches(false);
urlConnection.setDoInput(true);
// Connect explicitly to avoid errors in decoders if connection fails.
// 开启网络连接
urlConnection.connect();
if (isCancelled) {
// 如果取消,返回null
return null;
}
// 获取响应码
final int statusCode = urlConnection.getResponseCode();
if (statusCode / 100 == 2) {
// 如果成功,从服务端获取流
stream = urlConnection.getInputStream();
return stream;
} else if (statusCode / 100 == 3) {
// 重定向
String redirectUrlString = urlConnection.getHeaderField("Location");
if (TextUtils.isEmpty(redirectUrlString)) {
throw new IOException("Received empty or null redirect url");
}
URL redirectUrl = new URL(url, redirectUrlString);
return loadDataWithRedirects(redirectUrl, redirects + 1, url);
} else {
// 如果失败,抛出异常
if (statusCode == -1) {
throw new IOException("Unable to retrieve response code from HttpUrlConnection.");
}
throw new IOException("Request failed " + statusCode + ": " + urlConnection.getResponseMessage());
}
}
在decodeFromSourceData()中如果需要磁盘缓存的话,会进行磁盘缓存:
private Resource<T> decodeFromSourceData(A data) throws IOException {
final Resource<T> 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;
}
接着回到EngineRunnable的run(),进入成功处理的方法:
private void onLoadComplete(Resource resource) {
manager.onResourceReady(resource);
}
这里的manager就是一个EngineJob,这里就回调了EngineJob的onResourceReady():
@Override
public void onResourceReady(final Resource> resource) {
this.resource = resource;
MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();
}
MAIN_THREAD_HANDLER是一个主线程的Handler:
private static final Handler MAIN_THREAD_HANDLER = new Handler(Looper.getMainLooper(), new MainThreadCallback());
用来切换到主线程,给对应的target发送成功或者失败的消息:
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;
}
}
进入handleResultOnMainThread():
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);
for (ResourceCallback cb : cbs) {
if (!isInIgnoredCallbacks(cb)) {
engineResource.acquire();
// 回调ResourceCallback的onResourceReady()
// 在其中对应target会去处理资源
// 比如给ImageView设置下载好的图片
cb.onResourceReady(engineResource);
}
}
// Our request is complete, so we can release the resource.
engineResource.release();
}
参考:Glide 源码分析