美文网首页
Glide源码分析其一:基本流程

Glide源码分析其一:基本流程

作者: 美乃滋酱啊 | 来源:发表于2016-07-26 14:15 被阅读351次

    使用最为基本的用法:


    Glide.with(this).load(imageUr).into(imageView);

    Glide.with(this)

    分析

    0、先来看看RequestManager中的成员变量

    public class RequestManager implements LifecycleListener {
    private final Context context;
    /**生命周期管理**/
    private final Lifecycle lifecycle;
    private final RequestManagerTreeNode treeNode;
    private final RequestTracker requestTracker;
    private final Glide glide;
    /**配置注入者**/
    private final OptionsApplier optionsApplier;
    /**默认的配置**/
    private DefaultOptions options;
    }
    

    1、RequestManagerRetriever.get()获取到RequestManagerRetriever的单例;
    2、retriever.get(activity)获取到RequestManager的实例,作用是:
    这里会根据当前代码的所处线程和activity的类别(Activity,FragmentActivity,Frament和context(contextWrapper)),getApplicationManager到不同的RequestManager
    -如果是后台线程,会再次询问是否仍在后台线程中运行,如果是的话就创建一个RequestManager的对象

    private RequestManager getApplicationManager(Context context) {
    // Either an application context or we're on a background thread.
    if (applicationManager == null) {
    synchronized (this) {
    if (applicationManager == null) {
    // Normally pause/resume is taken care of by the fragment we add to the fragment or activity.
    // However, in this case since the manager attached to the application will not receive lifecycle
    // events, we must force the manager to start resumed using ApplicationLifecycle.
    applicationManager = new RequestManager(context.getApplicationContext(),
    new ApplicationLifecycle(), new EmptyRequestManagerTreeNode());
    }
    }
    }
    return applicationManager;
    }
    

    从注释中可以得知:处于后台运行中的或者使用Application创建的RequestManager,是不能监听到Application已经启动的回调的,于是就force the manager to start resumed using ApplicationLifecycle
    -如果在非后台线程:
    -FragmentActivity:

    public RequestManager get(FragmentActivity activity) {
    if (Util.isOnBackgroundThread()) {
    return get(activity.getApplicationContext());
    } else {
    assertNotDestroyed(activity);
    /**每次都会新建一个FragmentManager的对象**/
    FragmentManager fm = activity.getSupportFragmentManager();
    return supportFragmentGet(activity, fm);
    }
    }
    

    .load(imageUrl)

    /**
    * Returns a request builder to load the given {@link java.lang.String}.
    * signature.
    *
    * @see #fromString()
    * @see #load(Object)
    *
    * @param string A file path, or a uri or url handled by {@link com.bumptech.glide.load.model.UriLoader}.
    */
    public DrawableTypeRequest load(String string) {
    return (DrawableTypeRequest) fromString().load(string);
    }
    

    fromString()

    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");
    }
    /**利用配置注入者将配置注入**/
    return optionsApplier.apply(
    new DrawableTypeRequest(modelClass, streamModelLoader, fileDescriptorModelLoader, context,
    glide, requestTracker, lifecycle, optionsApplier));
    }
    

    这样,就得到了一个DrawableTypeRequest(继承与GenericRequestBuilder),以下是继承关系图(as中按F4)


    genericRequestBuildergenericRequestBuilder

    load()

    这个倒是没有什么,就是说明接下来使用的DrawableTypeRequest中的ModelType是何种类型的。而这个ModelType解释是:

    The type of model representing the resource.
    

    into()

    return into(glide.buildImageViewTarget(view, transcodeClass));
    

    会先生成一个ImageViewTarget

    public class ImageViewTargetFactory {
    @SuppressWarnings("unchecked")
    public Target buildTarget(ImageView view, Class clazz) {
    if (GlideDrawable.class.isAssignableFrom(clazz)) {
    return (Target) new GlideDrawableImageViewTarget(view);
    } else if (Bitmap.class.equals(clazz)) {
    return (Target) new BitmapImageViewTarget(view);
    } else if (Drawable.class.isAssignableFrom(clazz)) {
    return (Target) new DrawableImageViewTarget(view);
    } else {
    throw new IllegalArgumentException("Unhandled class: " + clazz
    + ", try .as*(Class).transcode(ResourceTranscoder)");
    }
    }
    }
    

    再来执行最终的生成request对象和request的过程

    /**
    * 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())");
    }
    /**其实就是获取view中的tag(Request对象)**/
    Request previous = target.getRequest();
    /**如果该view有已经有Request请求了,那么就先取消**/
    if (previous != null) {
    previous.clear();
    requestTracker.removeRequest(previous);
    previous.recycle();
    }
    Request request = buildRequest(target);
    /**设置view的tag **/
    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);
    }
    }
    

    接下来就是request开始执行:
    先来看看Engine都有什么成员变量

    public class Engine implements EngineJobListener,
    MemoryCache.ResourceRemovedListener,
    EngineResource.ResourceListener {
    private static final String TAG = "Engine";
    /**存储EngineJob的集合**/
    private final Map jobs;
    private final EngineKeyFactory keyFactory;
    private final MemoryCache cache;
    private final EngineJobFactory engineJobFactory;
    private final Map>> activeResources;
    private final ResourceRecycler resourceRecycler;
    private final LazyDiskCacheProvider diskCacheProvider;
    // Lazily instantiate to avoid exceptions if Glide is initialized on a background thread. See #295.
    private ReferenceQueue> resourceReferenceQueue;
    /**
    * Allows a request to indicate it no longer is interested in a given load.
    */
    public static class LoadStatus {
    private final EngineJob engineJob;
    private final ResourceCallback cb;
    public LoadStatus(ResourceCallback cb, EngineJob engineJob) {
    this.cb = cb;
    this.engineJob = engineJob;
    }
    public void cancel() {
    engineJob.removeCallback(cb);
    }
    }
    

    EngineRunnable****(实际进行图片请求的****task

    @Override
    public void run() {
    ......
    Exception exception = null;
    Resource resource = null;
    try {
    /** task运行的核心代码**/
    resource = decode();
    } catch (Exception e) {
    if (Log.isLoggable(TAG, Log.VERBOSE)) {
    Log.v(TAG, "Exception decoding", e);
    }
    exception = e;
    }
    ......
    }
    

    然后会执行decode()方法

    private Resource decode() throws Exception {
    if (isDecodingFromCache()) {
    return decodeFromCache();
    } else {
    return decodeFromSource();
    }
    }
    

    decodeResultFromCache()方法

    public Resource decodeResultFromCache() throws Exception {
    if (!diskCacheStrategy.cacheResult()) {
    return null;
    }
    long startTime = LogTime.getLogTime();
    Resource transformed = loadFromCache(resultKey);
    if (Log.isLoggable(TAG, Log.VERBOSE)) {
    logWithTimeAndKey("Decoded transformed from cache", startTime);
    }
    startTime = LogTime.getLogTime();
    /**这里把从cache中拿到的结果进行转码,后面做详细的分析**/
    Resource result = transcode(transformed);
    if (Log.isLoggable(TAG, Log.VERBOSE)) {
    logWithTimeAndKey("Transcoded transformed from cache", startTime);
    }
    return result;
    }
    
    private Resource decodeSource() throws Exception {
    Resource decoded = null;
    try {
    long startTime = LogTime.getLogTime();
    /**使用ExecutorService组织请求**/
    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;
    }
    

    其中fetcher是接口DataFetcher对象,DataFetcher的实现类包括:

    fetcherfetcher
    HttpUrlFetcher为例分析:
    @Override
    public InputStream loadData(Priority priority) throws Exception {
    return loadDataWithRedirects(glideUrl.toURL(), 0 /*redirects*/, null /*lastUrl*/, glideUrl.getHeaders());
    }
    
    

    -glideUrl.toURL():这里需要安全的装换到一个可以访问的URL,具体可见http://stackoverflow.com/questions/3286067/url-encoding-in-android

    final int statusCode = urlConnection.getResponseCode();
    if (statusCode / 100 == 2) {
    return getStreamForSuccessfulRequest(urlConnection);
    } 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, headers);
    } else {
    if (statusCode == -1) {
    throw new IOException("Unable to retrieve response code from HttpUrlConnection.");
    }
    throw new IOException("Request failed " + statusCode + ": " + urlConnection.getResponseMessage());
    }
    

    -如果返回的code是3开头的重定向请求,那么需要获取重定向的地址,重新组织访问。

    以上基本上走了一遍流程,下面还要具体分析glide中的各种管理细节。

    相关文章

      网友评论

          本文标题:Glide源码分析其一:基本流程

          本文链接:https://www.haomeiwen.com/subject/odvnjttx.html