Android_Glide源码分析
本文由 Luzhuo 编写,转发请保留该信息.
原文: http://blog.csdn.net/Rozol/article/details/73252999
Glide源码讲解
基本使用
Glide.with(this).load(url).into(imageview);
源码讲解
看下
.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的回调管理RequestManagerpublic 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(); } }
上面我们得到了
RequestManager
的对象,接着调用.load(url)
public DrawableTypeRequest<String> load(String string) { return (DrawableTypeRequest<String>) fromString().load(string); } @Override public 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
- 这个很简单,就是给
接着看
.into(imageview)
@Override public 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)
)发起请求, 并返回TargetrequestTracker.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); }
- 调用’request.begin()’执行请求, 状态改为
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); } } @Override public 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)
将图片资源保存到磁盘
- 首先会执行
- 磁盘没有找到,只能去网络找, EngineRunnable被放入了
在来看看
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") @Override public 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); } } @Override public void onResourceReady(Z resource, GlideAnimation<? super Z> glideAnimation) { if (glideAnimation == null || !glideAnimation.animate(resource, this)) { setResource(resource); // ←←← } } @Override protected void setResource(Bitmap resource) { view.setImageBitmap(resource); // ←←← }
- 可见主要是设置图片
- 会先
整理后的流程图
其他
通过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; } } }
源码解析:
首先看下构造方法
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访问记录
- 我们可以得知,
接着看下添加资源的方法
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第一个数据开始删的,因为被访问的元素都在链表末尾,第一个元素恰恰是最少被访问的
- 可知原来是在判断添加数据后size是否超过了maxSize,如果超过了就删除元素,直到
然后在看下获取资源的方法
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()方法,该被访问的结点会被移到列表末尾
清空缓存
public final void evictAll() { trimToSize(-1); // -1 will evict 0-sized elements }
- 也很简单,就是调用trimToSize(maxSize)把数据全部删掉,trimToSize(maxSize)的源码上面2拷贝过了,不再重复拷贝一份