Glide源码阅读一

来源:互联网 发布:明星淘宝店铺名称 编辑:程序博客网 时间:2024/05/24 01:31

从如下代码开始阅读Glide源码:

private static final Headers headers = new LazyHeaders.Builder().addHeader("Referer", AppCfg.FATE_IT_HTTP).build();if (TextUtils.isEmpty(sPic))    return;try {    GlideUrl glideUrl = new GlideUrl(sPic, headers);    Glide.with(context)            .load(glideUrl)            .dontAnimate()            .placeholder(defResImg)            .error(errResImg)            .transform(transformation)            .diskCacheStrategy(DiskCacheStrategy.ALL)            .into(view);} catch (Exception e) {    e.printStackTrace();}

第一步

首先分析with(context)

public static RequestManager with(Context context) {    RequestManagerRetriever retriever = RequestManagerRetriever.get();    return retriever.get(context);}

下面的的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);}

上面分情况

这是 getApplicationManager(context);

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

这是 get(Activity activity)

@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.HONEYCOMB)RequestManager fragmentGet(Context context, android.app.FragmentManager fm) {    RequestManagerFragment current = getRequestManagerFragment(fm);    RequestManager requestManager = current.getRequestManager();    if (requestManager == null) {        requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());        current.setRequestManager(requestManager);    }    return requestManager;}

以上分析的两种里面均会返回 RequestManager 对象,此时要看改对象构造函数

public RequestManager(Context context, Lifecycle lifecycle, RequestManagerTreeNode treeNode) {    this(context, lifecycle, treeNode, new RequestTracker(), new ConnectivityMonitorFactory());}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);}

第二个构造器里 this.glide = Glide.get(context); 开始调用 Glide 的单利模式了,进去看看

/** * Get the singleton. * * @return the singleton */public static Glide get(Context context) {    if (glide == null) {        synchronized (Glide.class) {            if (glide == null) {                Context applicationContext = context.getApplicationContext();                List<GlideModule> modules = new ManifestParser(applicationContext).parse();                GlideBuilder builder = new GlideBuilder(applicationContext);                for (GlideModule module : modules) {                    module.applyOptions(applicationContext, builder);                }                glide = builder.createGlide();                for (GlideModule module : modules) {                    module.registerComponents(applicationContext, glide);                }            }        }    }    return glide;}

单利生成 glide 对象 glide = builder.createGlide(); 用到 GlideBuilder 对象的 createGlide()。进去看看

Glide createGlide() {    if (sourceService == null) {        final int cores = Math.max(1, Runtime.getRuntime().availableProcessors());        sourceService = new FifoPriorityThreadPoolExecutor(cores);    }    if (diskCacheService == null) {        diskCacheService = new FifoPriorityThreadPoolExecutor(1);    }    MemorySizeCalculator calculator = new MemorySizeCalculator(context);    if (bitmapPool == null) {        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {            int size = calculator.getBitmapPoolSize();            bitmapPool = new LruBitmapPool(size);        } else {            bitmapPool = new BitmapPoolAdapter();        }    }    if (memoryCache == null) {        memoryCache = new LruResourceCache(calculator.getMemoryCacheSize());    }    if (diskCacheFactory == null) {        diskCacheFactory = new InternalCacheDiskCacheFactory(context);    }    if (engine == null) {        engine = new Engine(memoryCache, diskCacheFactory, diskCacheService, sourceService);    }    if (decodeFormat == null) {        decodeFormat = DecodeFormat.DEFAULT;    }    return new Glide(engine, memoryCache, bitmapPool, context, decodeFormat);}

createGlide() 里面创建 glide 对象的时候,初始化了很多对象,到此算是 Glide 的初始化吧

第二步

看网络请求 和 缓存策略

直接看into(view) 在 DrawableRequestBuilder 类里

public Target<GlideDrawable> into(ImageView view) {    return super.into(view);}

super.into(view) 到 GenericRequestBuilder 类里

public Target<TranscodeType> 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));}

进入这个 return into(glide.buildImageViewTarget(view, transcodeClass));

public <Y extends Target<TranscodeType>> 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;}

requestTracker.runRequest(request); 到 RequestTracker 类里

/** * Starts tracking the given request. */public void runRequest(Request request) {    requests.add(request);    if (!isPaused) {        request.begin();    } else {        pendingRequests.add(request);    }}

GenericRequest 类中实现 request.begin();

/** * {@inheritDoc} */@Overridepublic void begin() {    startTime = LogTime.getLogTime();    if (model == null) {        onException(null);        return;    }    status = Status.WAITING_FOR_SIZE;    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));    }}/** * A callback method that should never be invoked directly. */@Overridepublic 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<A, T> modelLoader = loadProvider.getModelLoader();    final DataFetcher<T> dataFetcher = modelLoader.getResourceFetcher(model, width, height);    if (dataFetcher == null) {        onException(new Exception("Failed to load model: \'" + model + "\'"));        return;    }    ResourceTranscoder<Z, R> 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(signature, width, height, dataFetcher, loadProvider, transformation, transcoder,
priority, isMemoryCacheable, diskCacheStrategy, this);

进入 Engin 看看,重点来了

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 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) {        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;    }    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);    }    EngineJob engineJob = engineJobFactory.build(key, isMemoryCacheable);    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);    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);}

EngineRunnable里面传入了 engineJob, decodeJob

engineJob.start(runnable);  // diskCacheService.submit(engineRunnable); // ExecutorService 涉及线程池

EngineRunnable线程开始干活了

@Overridepublic 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<?> decodeFromSource() throws Exception {    return decodeJob.decodeFromSource();}

DecodeJob 入场了

public Resource<Z> decodeFromSource() throws Exception {    Resource<T> decoded = decodeSource();    return transformEncodeAndTranscode(decoded);}private Resource<T> decodeSource() throws Exception {    Resource<T> 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 类来了,(数据提取类)
final A data = fetcher.loadData(priority); 数据提取有七种实现,我们来看 HttpUrlFetcher 吧

@Overridepublic 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<String, String> headers)        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.        }    }    urlConnection = connectionFactory.build(url);    for (Map.Entry<String, String> headerEntry : headers.entrySet()) {      urlConnection.addRequestProperty(headerEntry.getKey(), headerEntry.getValue());    }    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) {        return null;    }    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());    }}

是不是很熟悉,好了请求到的 InputStream 我们还是要返回的。回到 DecodeJob,看 decoded = decodeFromSourceData(data);

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

这里
decoded = cacheAndDecodeSourceData(data);是否缓存并 decode 解码
decoded = loadProvider.getSourceDecoder().decode(data, width, height); decode 选个合适的 ResourceDecoder 吧

以上都会返回 Resource ,逐级返回到 EngineRunnable 里面,开始给控件赋值了

给控件赋值

在 EngineRunnable 类里

@Overridepublic 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);    }}

来看 onLoadComplete(resource);

private void onLoadComplete(Resource resource) {    manager.onResourceReady(resource);}

点击去看看, 来到了 EngineJob 类里

@Overridepublic 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());

MainThreadCallback 里面

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);    for (ResourceCallback cb : cbs) {        if (!isInIgnoredCallbacks(cb)) {            engineResource.acquire();            cb.onResourceReady(engineResource);        }    }    // Our request is complete, so we can release the resource.    engineResource.release();}

在 EngineJob 里 cb.onResourceReady(engineResource); cb 是 ResourceCallback,它的实现类 EngineJob 和 GenericRequest;
GenericRequest 实现 onResourceReady 方法

@SuppressWarnings("unchecked")@Overridepublic void onResourceReady(Resource<?> resource) {    if (resource == null) {        onException(new Exception("Expected to receive a Resource<R> with an object of " + transcodeClass                + " inside, but instead got null."));        return;    }    Object received = resource.get();    if (received == null || !transcodeClass.isAssignableFrom(received.getClass())) {        releaseResource(resource);        onException(new Exception("Expected to receive an object of " + transcodeClass                + " but instead got " + (received != null ? received.getClass() : "") + "{" + received + "}"                + " inside Resource{" + resource + "}."                + (received != null ? "" : " "                    + "To indicate failure return a null Resource object, "                    + "rather than a Resource object containing null data.")        ));        return;    }    if (!canSetResource()) {        releaseResource(resource);        // We can't set the status to complete before asking canSetResource().        status = Status.COMPLETE;        return;    }    onResourceReady(resource, (R) received); // 这里}private void onResourceReady(Resource<?> resource, R result) {    // We must call isFirstReadyResource before setting status.    boolean isFirstResource = isFirstReadyResource();    status = Status.COMPLETE;    this.resource = resource;    if (requestListener == null || !requestListener.onResourceReady(result, model, target, loadedFromMemoryCache,            isFirstResource)) {        GlideAnimation<R> animation = animationFactory.build(loadedFromMemoryCache, isFirstResource);        target.onResourceReady(result, animation);  // 这里 选一种 target 实现吧 如: ImageViewTarget    }    notifyLoadSuccess();    if (Log.isLoggable(TAG, Log.VERBOSE)) {        logV("Resource ready in " + LogTime.getElapsedMillis(startTime) + " size: "                + (resource.getSize() * TO_MEGABYTE) + " fromCache: " + loadedFromMemoryCache);    }}

如果选择的是 ImageViewTarget 实现,来看看吧

@Overridepublic void onResourceReady(Z resource, GlideAnimation<? super Z> glideAnimation) {    if (glideAnimation == null || !glideAnimation.animate(resource, this)) {        setResource(resource); // 执行的是下面的抽象方法    }}protected abstract void setResource(Z resource);

实现类 BitmapImageViewTarget、DrawableImageViewTarget、GlideDrawableImageViewTarget 选一个吧,如: BitmapImageViewTarget

@Overrideprotected void setResource(Bitmap resource) {    view.setImageBitmap(resource);}

至此,Glide 加载图片及赋值算是完成了

注:还有好多东西需要研究,生命周期管理、缓存策略、资源加载策略

0 0
原创粉丝点击