Android_Glide源码分析

来源:互联网 发布:淘宝流量包怎么购买 编辑:程序博客网 时间:2024/05/22 09:47

Android_Glide源码分析


本文由 Luzhuo 编写,转发请保留该信息.
原文: http://blog.csdn.net/Rozol/article/details/73252999


Glide源码讲解

基本使用

Glide.with(this).load(url).into(imageview);

源码讲解

  1. 看下.with(this)做了什么

    public static RequestManager with(Context context) {    RequestManagerRetriever retriever = RequestManagerRetriever.get();    return retriever.get(context);}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);}@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;}@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)RequestManagerFragment getRequestManagerFragment(final android.app.FragmentManager fm) {    RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);    if (current == null) {        current = pendingRequestManagerFragments.get(fm);        if (current == null) {            current = new RequestManagerFragment();            pendingRequestManagerFragments.put(fm, current);            fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();            handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();        }    }    return current;}
    • 先调用Util.isOnMainThread()判断是否在主线程

      public static boolean isOnMainThread() {    return Looper.myLooper() == Looper.getMainLooper();}
       - 判断是否在主线程,原来是通过判断是否是主线程的Looper来判断的
    • 先调用assertNotDestroyed(activity)断言Activity还没有Destroy, 然后调用activity.getFragmentManager()获得一个FragmentManager
    • 调用getRequestManagerFragment(fm)获得RequestManagerFragment, 这个其实是一个用于实现生命周期管理的Fragment, 通过Fragment的回调管理RequestManager

      public class RequestManagerFragment extends Fragment {    @SuppressLint("ValidFragment")    RequestManagerFragment(ActivityFragmentLifecycle lifecycle) {        this.lifecycle = lifecycle;    }    @Override    public void onStart() {        super.onStart();        lifecycle.onStart();    }    @Override    public void onStop() {        super.onStop();        lifecycle.onStop();    }    @Override    public void onDestroy() {        super.onDestroy();        lifecycle.onDestroy();    }}
      • 可见RequestManager实现了LifecycleListener

        public class RequestManager implements LifecycleListener {    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);    }    @Override    public void onStart() {        // onStart might not be called because this object may be created after the fragment/activity's onStart method.        resumeRequests();    }    @Override    public void onStop() {        pauseRequests();    }    @Override    public void onDestroy() {        requestTracker.clearRequests();    }}
  2. 上面我们得到了RequestManager的对象,接着调用.load(url)

    public DrawableTypeRequest<String> load(String string) {    return (DrawableTypeRequest<String>) fromString().load(string);}@Overridepublic DrawableRequestBuilder<ModelType> load(ModelType model) {    super.load(model);    return this;}public GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> load(ModelType model) {    this.model = model;    isModelSet = true;    return this;}
    • 这个很简单,就是给GenericRequestBuilder初始化值, 并返回了DrawableRequestBuilder
  3. 接着看.into(imageview)

    @Overridepublic Target<GlideDrawable> into(ImageView view) {    return super.into(view);}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;}
    • Request previous = target.getRequest()获取就的Request,如果有就删除他, 然后(buildRequest(target))构建新的Request, 进行绑定与(requestTracker.runRequest(request))发起请求, 并返回Target
    • requestTracker.runRequest(request)是如何执行的呢?

      public class RequestTracker {    private final Set<Request> requests = Collections.newSetFromMap(new WeakHashMap<Request, Boolean>());    private final List<Request> pendingRequests = new ArrayList<Request>();    private boolean isPaused;    public void runRequest(Request request) {        requests.add(request); // ←←←        if (!isPaused) {            request.begin(); // ←←←        } else {            pendingRequests.add(request);        }    }}public final class GenericRequest<A, T, Z, R> implements Request, SizeReadyCallback, ResourceCallback {    @Override    public 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));        }    }    @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<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));        }    }}
      • 调用’request.begin()’执行请求, 状态改为Status.WAITING_FOR_SIZE,并调用onSizeReady(overrideWidth, overrideHeight)将状态改为Status.RUNNING,计算了一个四舍五入的宽高,然后将engine.load()发起了请求
      • loadStatus = engine.load(signature, width, height, dataFetcher, loadProvider, transformation, transcoder,
        priority, isMemoryCacheable, diskCacheStrategy, this);
        里做了什么?

        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);}
    • EngineResource<?> cached = loadFromCache(key, isMemoryCacheable)他会先去缓存(内存缓存)里找资源

      private EngineResource<?> loadFromCache(Key key, boolean isMemoryCacheable) {    if (!isMemoryCacheable) {        return null;    }    EngineResource<?> cached = getEngineResourceFromCache(key); // ←←←    if (cached != null) {        cached.acquire();        activeResources.put(key, new ResourceWeakReference(key, cached, getReferenceQueue()));    }    return cached;}private static class ResourceWeakReference extends WeakReference<EngineResource<?>> {    private final Key key;    public ResourceWeakReference(Key key, EngineResource<?> r, ReferenceQueue<? super EngineResource<?>> q) {        super(r, q);        this.key = key;    }}private EngineResource<?> getEngineResourceFromCache(Key key) {    Resource<?> cached = cache.remove(key); // ←←←    final EngineResource result;    if (cached == null) {        result = null;    } else if (cached instanceof EngineResource) {        // Save an object allocation if we've cached an EngineResource (the typical case).        result = (EngineResource) cached;    } else {        result = new EngineResource(cached, true /*isCacheable*/);    }    return result;}public class LruCache<T, Y> {    private final LinkedHashMap<T, Y> cache = new LinkedHashMap<T, Y>(100, 0.75f, true);    public Y remove(T key) {        final Y value = cache.remove(key);        if (value != null) {            currentSize -= getSize(value);        }        return value;    }}
       - 如果`getEngineResourceFromCache(key)`找到资源,则该资源会被用`WeakReference`(弱引用)一层,然后添加到activeResources - 调用`Resource<?> cached = cache.remove(key)`获取的资源是从LruCache获取的
      • EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);找不到的话,在到Active里找资源

        private EngineResource<?> loadFromActiveResources(Key key, boolean isMemoryCacheable) {    if (!isMemoryCacheable) {        return null;    }    EngineResource<?> active = null;    WeakReference<EngineResource<?>> activeRef = activeResources.get(key);    if (activeRef != null) {        active = activeRef.get();        if (active != null) {            active.acquire();        } else {            activeResources.remove(key);        }    }    return active;}
        • 可见然后会看getEngineResourceFromCache(key)activeResources(弱引用资源)添加的资源还在吗?如果已经被回收了,就删除key,然后返回资源
      • EngineJob engineJob = engineJobFactory.build(key, isMemoryCacheable)如果内存和弱引用集合都没有就创建EngineJob, EngineJob有diskCacheService和sourceService两个线程池

        class EngineJob implements EngineRunnable.EngineRunnableManager {    private final Key key;    private final ExecutorService diskCacheService;    private final ExecutorService sourceService;    public EngineJob(Key key, ExecutorService diskCacheService, ExecutorService sourceService, boolean isCacheable,            EngineJobListener listener) {        this(key, diskCacheService, sourceService, isCacheable, listener, DEFAULT_FACTORY);    }    public void start(EngineRunnable engineRunnable) {        this.engineRunnable = engineRunnable;        future = diskCacheService.submit(engineRunnable); // ←←←    }}class EngineRunnable implements Runnable, Prioritized {    @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); // ←←←        }    }    private Resource<?> decode() throws Exception {        if (isDecodingFromCache()) {            return decodeFromCache(); // ←←←        } else {            return decodeFromSource(); // ←←←        }    }    private boolean isDecodingFromCache() {        return stage == Stage.CACHE;    }    private Resource<?> decodeFromCache() throws Exception {        Resource<?> result = null;        try {            result = decodeJob.decodeResultFromCache(); // ←←←        } catch (Exception e) {            if (Log.isLoggable(TAG, Log.DEBUG)) {                Log.d(TAG, "Exception decoding result from cache: " + e);            }        }        if (result == null) {            result = decodeJob.decodeSourceFromCache(); // ←←←        }        return result;    }}
        • 会先result = decodeJob.decodeResultFromCache()从处理过的资源磁盘缓存找, 没有找到, 则result = decodeJob.decodeSourceFromCache()在从原图磁盘缓存找
        • 如果都没找到, 则执行onLoadFailed(exception)

          private void onLoadFailed(Exception e) {    if (isDecodingFromCache()) {        stage = Stage.SOURCE;        manager.submitForSource(this);    } else {        manager.onException(e);    }}@Overridepublic void submitForSource(EngineRunnable runnable) {    future = sourceService.submit(runnable);}
          • 磁盘没有找到,只能去网络找, EngineRunnable被放入了sourceService线程池中并执行
          • 状态从Stage.CACHE变为了Stage.SOURCE, 于是decode()里执行decodeFromSource()

            class DecodeJob<A, T, Z> {    private Resource<?> decodeFromSource() throws Exception {        return decodeJob.decodeFromSource();    }    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;    }    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;    }    private Resource<T> cacheAndDecodeSourceData(A data) throws IOException {        long startTime = LogTime.getLogTime();        SourceWriter<A> writer = new SourceWriter<A>(loadProvider.getSourceEncoder(), data); // ←←←        diskCacheProvider.getDiskCache().put(resultKey.getOriginalKey(), writer); // ←←←        if (Log.isLoggable(TAG, Log.VERBOSE)) {            logWithTimeAndKey("Wrote source to cache", startTime);        }        startTime = LogTime.getLogTime();        Resource<T> result = loadFromCache(resultKey.getOriginalKey());        if (Log.isLoggable(TAG, Log.VERBOSE) && result != null) {            logWithTimeAndKey("Decoded source from cache", startTime);        }        return result;    }    private Resource<Z> transformEncodeAndTranscode(Resource<T> decoded) {        long startTime = LogTime.getLogTime();        Resource<T> transformed = transform(decoded); // ←←←        if (Log.isLoggable(TAG, Log.VERBOSE)) {            logWithTimeAndKey("Transformed resource from source", startTime);        }        writeTransformedToCache(transformed); // ←←←        startTime = LogTime.getLogTime();        Resource<Z> result = transcode(transformed); // ←←←        if (Log.isLoggable(TAG, Log.VERBOSE)) {            logWithTimeAndKey("Transcoded transformed from source", startTime);        }        return result;    }}public class HttpUrlFetcher implements DataFetcher<InputStream> {    @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<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());        }    }}
            • 首先会执行Resource<T> decoded = decodeSource()进行获取数据,然后执行transformEncodeAndTranscode(decoded)进行处理数据:Resource<T> transformed = transform(decoded)剪裁,writeTransformedToCache(transformed)写入磁盘,Resource<Z> result = transcode(transformed)转码
            • decodeSource()里会执行final A data = fetcher.loadData(priority)来获取数据,然后执行decoded = decodeFromSourceData(data)来解析并保存数据
            • 通过查看fetcher.loadData(priority)代码,我们发现原来是用urlConnection发起的网络请求
            • 在看看decodeFromSourceData(data), 执行了decoded = cacheAndDecodeSourceData(data)将图片资源保存到磁盘
        • 在来看看onLoadComplete(resource);做了什么?

          private void onLoadComplete(Resource resource) {    manager.onResourceReady(resource);}class EngineJob implements EngineRunnable.EngineRunnableManager {    private static final Handler MAIN_THREAD_HANDLER = new Handler(Looper.getMainLooper(), new MainThreadCallback());    @Override    public void onResourceReady(final Resource<?> resource) {        this.resource = resource;        MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget(); // ←←←    }}
          • 可见是用Handler发了一个消息, 那么接着看看消息是怎么处理的

            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();}@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); // ←←←    }    notifyLoadSuccess();    if (Log.isLoggable(TAG, Log.VERBOSE)) {        logV("Resource ready in " + LogTime.getElapsedMillis(startTime) + " size: "                + (resource.getSize() * TO_MEGABYTE) + " fromCache: " + loadedFromMemoryCache);    }}@Overridepublic void onResourceReady(Z resource, GlideAnimation<? super Z> glideAnimation) {    if (glideAnimation == null || !glideAnimation.animate(resource, this)) {        setResource(resource); // ←←←    }}@Overrideprotected void setResource(Bitmap resource) {    view.setImageBitmap(resource); // ←←←}
            • 可见主要是设置图片
  4. 整理后的流程图

其他

通过Fragment的生命周期实现自身的管理

  • XXX管理的代码

    package me.luzhuo.glidedemo.other.lifecycle;import android.content.Context;import android.os.Handler;import android.os.Looper;import android.util.Log;import me.luzhuo.glidedemo.other.lifecycle.inter.Lifecycle;import me.luzhuo.glidedemo.other.lifecycle.inter.LifecycleListener;public class Manager implements LifecycleListener {    private final String TAG = Manager.class.getSimpleName();    private final Context context;    private final Lifecycle lifecycle;    public Manager(Context context, final Lifecycle lifecycle) {        this.context = context.getApplicationContext();        this.lifecycle = lifecycle;        if (!Utils.isOnMainThread()) {            new Handler(Looper.getMainLooper()).post(new Runnable() {                @Override                public void run() {                    lifecycle.addListener(Manager.this);                }            });        } else {            lifecycle.addListener(this);        }    }    public static Manager with(Context context) {        ManagerRetriever retriever = ManagerRetriever.get();        return retriever.get(context);    }    @Override    public void onStart() {        Log.e(TAG, "Manager 将开始工作");    }    @Override    public void onStop() {        Log.e(TAG, "Manager 将暂停工作");    }    @Override    public void onDestroy() {        Log.e(TAG, "Manager 将停止工作");    }}
  • ManagerRetriever主要做的是构建Fragment,并绑定鉴定,这里的代码多,是因为传入Content做相应的Fragment生成和管理

    public class ManagerRetriever {    Manager applicationManager;    static final String FRAGMENT_TAG = "me.luzhuo.glidedemo";    private static final ManagerRetriever INSTANCE = new ManagerRetriever();    public static ManagerRetriever get() {        return INSTANCE;    }    public Manager get(Context context) {        if (context == null) {            throw new IllegalArgumentException("You cannot start a load on a null Context");        } else if (Utils.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 Manager get(FragmentActivity activity) {        if (!Utils.isOnMainThread()) {            return get(activity.getApplicationContext());        } else {            assertNotDestroyed(activity);            FragmentManager fm = activity.getSupportFragmentManager();            return fragmentGet(activity, fm);        }    }    public Manager get(Fragment fragment) {        if (fragment.getActivity() == null) {            throw new IllegalArgumentException("You cannot start a load on a fragment before it is attached");        }        if (!Utils.isOnMainThread()) {            return get(fragment.getActivity().getApplicationContext());        } else {            FragmentManager fm = fragment.getChildFragmentManager();            return fragmentGet(fragment.getActivity(), fm);        }    }    @TargetApi(Build.VERSION_CODES.HONEYCOMB)    public Manager get(Activity activity) {        if (!Utils.isOnMainThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {            return get(activity.getApplicationContext());        } else {            assertNotDestroyed(activity);            android.app.FragmentManager fm = activity.getFragmentManager();            return fragmentGet2(activity, fm);        }    }    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)    private static void assertNotDestroyed(Activity activity) {        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && activity.isDestroyed()) {            throw new IllegalArgumentException("You cannot start a load for a destroyed activity");        }    }    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)    public Manager 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 (!Utils.isOnMainThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {            return get(fragment.getActivity().getApplicationContext());        } else {            android.app.FragmentManager fm = fragment.getChildFragmentManager();            return fragmentGet2(fragment.getActivity(), fm);        }    }    private Manager getApplicationManager(Context context) {        // Either an application context or we're on a background thread.        if (applicationManager == null) {            synchronized (this) {                if (applicationManager == null) {                    applicationManager = new Manager(context.getApplicationContext(), getLifecycle);                }            }        }        return applicationManager;    }    Lifecycle getLifecycle = new Lifecycle() {        @Override        public void addListener(LifecycleListener listener) {            listener.onStart();        }    };    Manager fragmentGet(Context context, FragmentManager fm) {        LifecycleFragment current = getManagerFragment(fm);        Manager manager = current.getManager();        if (manager == null) {            manager = new Manager(context, current.getLifecycle());            current.setManager(manager);        }        return manager;    }    @TargetApi(Build.VERSION_CODES.HONEYCOMB)    Manager fragmentGet2(Context context, android.app.FragmentManager fm) {        LifecycleFragment2 current = getManagerFragment2(fm);        Manager manager = current.getManager();        if (manager == null) {            manager = new Manager(context, current.getLifecycle());            current.setManager(manager);        }        return manager;    }    LifecycleFragment getManagerFragment(final FragmentManager fm) {        LifecycleFragment current = (LifecycleFragment) fm.findFragmentByTag(FRAGMENT_TAG);        if (current == null) {            if (current == null) {                current = new LifecycleFragment();                fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();            }        }        return current;    }    LifecycleFragment2 getManagerFragment2(final android.app.FragmentManager fm) {        LifecycleFragment2 current = (LifecycleFragment2) fm.findFragmentByTag(FRAGMENT_TAG);        if (current == null) {            if (current == null) {                current = new LifecycleFragment2();                fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();            }        }        return current;    }}
  • Utils就一个isOnMainThread()方法,根据Looper判断是否是主线程

    public class Utils {    public static boolean isOnMainThread() {        return Looper.myLooper() == Looper.getMainLooper();    }}
  • 有两个Fragment,由于代码一样,仅仅是Fragment的包的引用不同,这里就写一份吧

    package me.luzhuo.glidedemo.other.lifecycle.fragment;import android.annotation.SuppressLint;import android.app.Activity;import android.support.v4.app.Fragment;import android.util.Log;import me.luzhuo.glidedemo.other.lifecycle.Manager;import me.luzhuo.glidedemo.other.lifecycle.inter.LifecycleImpl;public class LifecycleFragment extends Fragment{    private static final String TAG = LifecycleFragment.class.getSimpleName();    private Manager manager;    private final LifecycleImpl lifecycle;    public LifecycleFragment() {        this(new LifecycleImpl());    }    // For testing only.    @SuppressLint("ValidFragment")    public LifecycleFragment(LifecycleImpl lifecycle) {        this.lifecycle = lifecycle;    }    public LifecycleImpl getLifecycle() {        return lifecycle;    }    public void setManager(Manager manager) {        this.manager = manager;    }    public Manager getManager() {        return this.manager;    }    @Override    public void onAttach(Activity activity) {        super.onAttach(activity);        Log.e(TAG, "onAttach");    }    @Override    public void onDetach() {        super.onDetach();        Log.e(TAG, "onDetach");    }    @Override    public void onStart() {        super.onStart();        Log.e(TAG, "onStart");        lifecycle.onStart();    }    @Override    public void onStop() {        super.onStop();        Log.e(TAG, "onStop");        lifecycle.onStop();    }    @Override    public void onDestroy() {        super.onDestroy();        Log.e(TAG, "onDestroy");        lifecycle.onDestroy();    }    @Override    public void onLowMemory() {        Log.e(TAG, "onLowMemory");        super.onLowMemory();    }}
  • 接下来是定义的一些接口,和接口的实现

    public interface Lifecycle {    void addListener(LifecycleListener listener);}public class LifecycleImpl implements Lifecycle {    private final List<LifecycleListener> lifecycleListeners = new ArrayList();    private boolean isStarted;    private boolean isDestroyed;    @Override    public void addListener(LifecycleListener listener) {        lifecycleListeners.add(listener);        if (isDestroyed) {            listener.onDestroy();        } else if (isStarted) {            listener.onStart();        } else {            listener.onStop();        }    }    public void onStart() {        isStarted = true;        for (LifecycleListener lifecycleListener : lifecycleListeners) {            lifecycleListener.onStart();        }    }    public void onStop() {        isStarted = false;        for (LifecycleListener lifecycleListener : lifecycleListeners) {            lifecycleListener.onStop();        }    }    public void onDestroy() {        isDestroyed = true;        for (LifecycleListener lifecycleListener : lifecycleListeners) {            lifecycleListener.onDestroy();        }    }}public interface LifecycleListener {    void onStart();    void onStop();    void onDestroy();}
    • 用于测试的Activity
    public class LifecycleTestActivity extends AppCompatActivity {    private static final String TAG = "Test";    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Manager.with(this);    }    @Override    protected void onStart() {        super.onStart();        Log.e(TAG, "onStart");    }    @Override    protected void onStop() {        super.onStop();        Log.e(TAG, "onStop");    }    @Override    protected void onDestroy() {        super.onDestroy();        Log.e(TAG, "onDestroy");    }}
  • 打印测试结果

LinkedHashMap的数据结构和算法

  • 首先看下该数据结构的构造方法

    public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> {    private transient LinkedHashMapEntry<K,V> header;    private final boolean accessOrder;    public LinkedHashMap(int initialCapacity,                         float loadFactor,                         boolean accessOrder) {        super(initialCapacity, loadFactor);        this.accessOrder = accessOrder;    }    @Override    void init() {        header = new LinkedHashMapEntry<>(-1, null, null, null);        header.before = header.after = header;    }}
    - 我们可以看到有一个`LinkedHashMapEntry<K,V> header`**头结点**,还有一个布尔类型的`accessOrder`用来控制是否按访问顺序排序
  • 看数据结构,当然必须先把结点理清楚

    private static class LinkedHashMapEntry<K,V> extends HashMapEntry<K,V> {    // These fields comprise the doubly linked list used for iteration.    LinkedHashMapEntry<K,V> before, after;    LinkedHashMapEntry(int hash, K key, V value, HashMapEntry<K,V> next) {        super(hash, key, value, next);    }    /**     * Removes this entry from the linked list.     */    private void remove() {        before.after = after;        after.before = before;    }    /**     * Inserts this entry before the specified existing entry in the list.     */    private void addBefore(LinkedHashMapEntry<K,V> existingEntry) {        after  = existingEntry;        before = existingEntry.before;        before.after = this;        after.before = this;    }    /**     * This method is invoked by the superclass whenever the value     * of a pre-existing entry is read by Map.get or modified by Map.set.     * If the enclosing Map is access-ordered, it moves the entry     * to the end of the list; otherwise, it does nothing.     */    void recordAccess(HashMap<K,V> m) {        LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;        if (lm.accessOrder) {            lm.modCount++;            remove();            addBefore(lm.header);        }    }    void recordRemoval(HashMap<K,V> m) {        remove();    }}
    • 从结点内内LinkedHashMapEntry<K,V> before, after可以看出这是一个双向循环的链式数据结构
    • 可见数据结构是这样的,接下来我们就来仔细分析下结点里的代码
    • remove()移除结点
    • addBefore()在指定结点前添加结点
    • recordAccess()在记录访问次数,lm.modCount++访问次数+1, 然后通过remove()删除结点,再将自己addBefore(lm.header)添加到头结点之前,也就是链表的末尾
    • recordRemoval()删除访问记录,只是简单的删除了结点
  • 链式的数据结构基本讲解的差不多了, 接下来简单的讲下 增删查

    • 增加

      void createEntry(int hash, K key, V value, int bucketIndex) {    HashMapEntry<K,V> old = table[bucketIndex];    LinkedHashMapEntry<K,V> e = new LinkedHashMapEntry<>(hash, key, value, old);    table[bucketIndex] = e;    e.addBefore(header);    size++;}
      • 创建结点,创建后将结点添加到链表的末尾
    • public void clear() {    super.clear();    header.before = header.after = header;}
      • 将header结点的before和after指针都指向自己
    • 查(获取)

      public V get(Object key) {    LinkedHashMapEntry<K,V> e = (LinkedHashMapEntry<K,V>)getEntry(key);    if (e == null)        return null;    e.recordAccess(this);    return e.value;}
      • 根据key从hashmap中获取Entry,然后对该结点进行访问记录,返回其值

LruCache

  • 基本使用;

    • LruCache使用代码:

      import android.annotation.SuppressLint;import android.graphics.Bitmap;import android.os.Build;import android.support.v4.util.LruCache;import android.util.Log;public class ImageCache {    // 使用最大可用内存值的1/5作为缓存的大小。    private static final int MAXSIZE = (int) (Runtime.getRuntime().maxMemory() / 5);    private static ImageCache cache = new ImageCache();    public static ImageCache getInstance() {        return cache;    }    // LruCache<标记, 图片>    private LruCache<Object, Bitmap> lrucache;// 图片的缓存;设置的Value必须能够计算出所占有的内存的大小    private ImageCache() {        lrucache = new LruCache<Object, Bitmap>(MAXSIZE) {            @Override            protected int sizeOf(Object key, Bitmap value) {                System.out.println("内存已缓存:"+lrucache.size()+";总空间:"+MAXSIZE);                // size的变动代表该bitmap占用的内存大小                return getSize(value);            }            @Override            protected void entryRemoved(boolean evicted, Object key, Bitmap oldValue, Bitmap newValue) {                // evicted 为true表示MAXSIZE不够用                if (evicted) {                    Log.d("memoryLruCache", "remove:" + key.toString());                }                super.entryRemoved(evicted, key, oldValue, newValue);            }        };    }    /**     * 获取图片占用内存的大小     * @param value     * @return     */    @SuppressLint("NewApi")    private int getSize(Bitmap value) {        // 如果当前版本 >= API12        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {            return value.getByteCount();        }        return value.getRowBytes() * value.getHeight();    }    /**     * 添加图片,如果添加的图片超过了设置的最大内存缓存,将清除一部分旧的图片     * @param key     * @param value     */    public void put(Object key, Bitmap value) {        lrucache.put(key, value);    }    public Bitmap get(Object key) {        Bitmap bitmap = lrucache.get(key);        return bitmap;    }    /**     * 清空所有缓存,包括内存和磁盘     */    public void clear() {        lrucache.evictAll();    }}
    • 测试代码:

      package me.luzhuo.lrucachedemo;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Environment;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.ListView;import android.widget.TextView;import java.io.File;import me.luzhuo.lrucachedemo.utils.ImageCache;import static android.R.attr.bitmap;import static android.R.attr.key;public class MainActivity extends AppCompatActivity {    private ListView listview;    private int key;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        // 添加到内存缓存        Bitmap bitmap = BitmapFactory.decodeFile(new File(Environment.getExternalStorageDirectory(),"abc.jpg").getPath());        // hashcode的计算方法        key = bitmap.hashCode();        key = 31 * key + MainActivity.class.getSimpleName().hashCode();        ImageCache.getInstance().put(key, bitmap);        initView();        initData();    }    private void initView() {        listview = (ListView) findViewById(R.id.listView);    }    private void initData() {        listview.setAdapter(new ImageAdapter());    }    class ImageAdapter extends BaseAdapter {        @Override        public int getCount() {            return 100;        }        @Override        public Object getItem(int position) {            return null;        }        @Override        public long getItemId(int position) {            return 0;        }        class ViewHodler{            TextView textview;            ImageView imageview;        }        @Override        public View getView(int position, View convertView, ViewGroup parent) {            ViewHodler viewHodler;            if(convertView==null){                viewHodler = new ViewHodler();                convertView = View.inflate(MainActivity.this, R.layout.item, null);                viewHodler.textview = (TextView) convertView.findViewById(R.id.textview);                viewHodler.imageview = (ImageView) convertView.findViewById(R.id.imageview);                convertView.setTag(viewHodler);            }else{                viewHodler = (ViewHodler) convertView.getTag();            }            viewHodler.textview.setText("第"+position+"张");            // 从内存缓存获取数据            Bitmap bitmap = ImageCache.getInstance().get(key);            viewHodler.imageview.setImageBitmap(bitmap);            return convertView;        }    }}
  • 源码解析:

    1. 首先看下构造方法

      public class LruCache<K, V> {    private final LinkedHashMap<K, V> map;    /** Size of this cache in units. Not necessarily the number of elements. */    private int size;    private int maxSize;    private int putCount;    private int createCount;    private int evictionCount;    private int hitCount;    private int missCount;    /**     * @param maxSize for caches that do not override {@link #sizeOf}, this is     *     the maximum number of entries in the cache. For all other caches,     *     this is the maximum sum of the sizes of the entries in this cache.     */    public LruCache(int maxSize) {        if (maxSize <= 0) {            throw new IllegalArgumentException("maxSize <= 0");        }        this.maxSize = maxSize;        this.map = new LinkedHashMap<K, V>(0, 0.75f, true);    }}
      • 我们可以得知,maxSize用于限制资源最大的可使用内存, 用LinkedHashMap<K, V> map来存储资源,并且要求LinkedHashMap访问记录
    2. 接着看下添加资源的方法

      public final V put(K key, V value) {    if (key == null || value == null) {        throw new NullPointerException("key == null || value == null");    }    V previous;    synchronized (this) {        putCount++;        size += safeSizeOf(key, value);        previous = map.put(key, value);        if (previous != null) {            size -= safeSizeOf(key, previous);        }    }    if (previous != null) {        entryRemoved(false, key, previous, value);    }    trimToSize(maxSize);    return previous;}
      • 可见添加资源时,会回调safeSizeOf(key, value)获取该资源的大小,然后加到size, 然后调用LinkedHashMap的put()方法添加资源,返回previous

        • 在LinkedHashMap中没有put()方法,看来是调用了HashMap的put()方法

          public V put(K key, V value) {    // ...    for (HashMapEntry<K,V> e = table[i]; e != null; e = e.next) {        Object k;        if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {            V oldValue = e.value;            e.value = value;            e.recordAccess(this);            return oldValue;        }    }    modCount++;    addEntry(hash, key, value, i);    return null;}
        • 调用HashMap的put(),如果这个key已经存在则返回旧元素,否则会调用addEntry()添加元素,然后返回null

          void addEntry(int hash, K key, V value, int bucketIndex) {    // ...    createEntry(hash, key, value, bucketIndex);}
        • 然后会调用LinkedHashMap中的createEntry()方法,因为LinkedHashMap重写了该方法,该方法创建了一个结点,并将其添加到链表末尾

      • 我们继续往下看,如果previous返回不为null,说明这个元素存在,调用了size -= safeSizeOf(key, previous),把加上的资源大小减掉

      • 然后会回调entryRemoved(false, key, previous, value)告知该资源没有添加到LruCache里,第一个boolean值表示该资源是否是因为超过限制而被移除,false表示不是,true表示是内存不足而删除.
      • 然后调用trimToSize(maxSize),我们看下做了什么

        public void trimToSize(int maxSize) {    while (true) {        K key;        V value;        synchronized (this) {            if (size < 0 || (map.isEmpty() && size != 0)) {                throw new IllegalStateException(getClass().getName()                        + ".sizeOf() is reporting inconsistent results!");            }            if (size <= maxSize || map.isEmpty()) {                break;            }            Map.Entry<K, V> toEvict = map.entrySet().iterator().next();            key = toEvict.getKey();            value = toEvict.getValue();            map.remove(key);            size -= safeSizeOf(key, value);            evictionCount++;        }        entryRemoved(true, key, value, null);    }}
        • 可知原来是在判断添加数据后size是否超过了maxSize,如果超过了就删除元素,直到size <= maxSize || map.isEmpty()为止,删除数据是从LinkedHashMap第一个数据开始删的,因为被访问的元素都在链表末尾,第一个元素恰恰是最少被访问的
    3. 然后在看下获取资源的方法

      public final V get(K key) {    if (key == null) {        throw new NullPointerException("key == null");    }    V mapValue;    synchronized (this) {        mapValue = map.get(key);        if (mapValue != null) {            hitCount++;            return mapValue;        }        missCount++;    }    // ...}
      • 就是调用LinkedHashMap的get()方法,该被访问的结点会被移到列表末尾
    4. 清空缓存

      public final void evictAll() {    trimToSize(-1); // -1 will evict 0-sized elements}
      • 也很简单,就是调用trimToSize(maxSize)把数据全部删掉,trimToSize(maxSize)的源码上面2拷贝过了,不再重复拷贝一份
原创粉丝点击