Glide源码分析

使用

官方给出的简单使用的例子:

// 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()

首先来看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对象。

生命周期事件的传递图
Glide源码分析_第1张图片

load()

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()。

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

into()的流程图如下:
Glide源码分析_第2张图片

接着进入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));
        }
    }

其中主要做的一件事情就是调用Engineload():

    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()在一连串函数调用链之后会进入DecodeJobdecodeSource():

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

进入DataFetcherloadData(),根据来源的不同有不同的实现,我们这里看下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();
    }

EngineJob的load()流程图
Glide源码分析_第3张图片

参考:Glide 源码分析

你可能感兴趣的:(Android)