版本 4.9.0
问题
Glide 如何实现与生命周期的绑定?
Glide 如何实现缓存?
Glide 如何实现图片压缩?
Glide 如何实现与生命周期的绑定?
创建 RequestManger, 将其与 with() 传入 Activity, Fragment 的生命周期绑定, 这样做的好处是当 Activity/Fragment stop/destroy 时,RequestManager 也会做相应操作,如停掉图片加载
绑定 Application Context
首先无论 with() 传入的是什么,只要是在子线程中调用, 创建的 RequestManger 与 Application Context 绑定,这样创建的 RequestMangager 的生命周期与
if (Util.isOnBackgroundThread()) {
return get(fragment.getActivity().getApplicationContext());
} else {
… …
}
这样做的目的是防止 Activity,Fragment 内存泄漏
Activity 与 FramgentActivity
class RequestManagerFragment {
… …
private final ActivityFragmentLifecycle 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();
unregisterFragmentWithRoot();
}
… …
}
class ActivityFragmentLifecycle implements Lifecycle {
@Override
public void addListener(@NonNull LifecycleListener listener) {
lifecycleListeners.add(listener);
if (isDestroyed) {
listener.onDestroy();
} else if (isStarted) {
listener.onStart();
} else {
listener.onStop();
}
}
void onStart() {
isStarted = true;
for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
lifecycleListener.onStart();
}
}
void onStop() {
isStarted = false;
for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
lifecycleListener.onStop();
}
}
void onDestroy() {
isDestroyed = true;
for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
lifecycleListener.onDestroy();
}
}
}
RequestManagerFragment current = getRequestManagerFragment(fm,
parentHint, isParentVisible);
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
// TODO(b/27524013): Factor out this Glide.get() call.
Glide glide = Glide.get(context);
requestManager = factory.build(glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
current.setRequestManager(requestManager);
}
RequestManagerFragment 中创建了并对外提供 ActivityFragmentLifecycle 对象, 创建 RequestManager 时,传入 ActivityFragmentLifecycle 对象
RequestManager(
Glide glide,
Lifecycle lifecycle,
RequestManagerTreeNode treeNode,
RequestTracker requestTracker,
ConnectivityMonitorFactory factory,
Context context) {
… …
lifecycle.addListener(this);
… …
}
@Override
public synchronized void onStart() {
resumeRequests();
targetTracker.onStart();
}
@Override
public synchronized void onStop() {
pauseRequests();
targetTracker.onStop();
}
@Override
public synchronized void onDestroy() {
targetTracker.onDestroy();
for (Target<?> target : targetTracker.getAll()) {
clear(target);
}
targetTracker.clear();
requestTracker.clearRequests();
lifecycle.removeListener(this);
lifecycle.removeListener(connectivityMonitor);
mainHandler.removeCallbacks(addSelfToLifecycle);
glide.unregisterRequestManager(this);
}
这样 RequestManger.onStart(),onStop(),onDestroy() 与 Activity 的生命周期通过 Activity 绑定的空 Fragment 实现了绑定
Fragment 与 Activity 的绑定方式类似,
FragmentManager fm = fragment.getChildFragmentManager();
将 RequestManger.onStart(),onStop(),onDestroy() 与 Fragment 的生命周期通过 Fragment 绑定的空 Fragment 实现的绑定
View 通过 View 可以获取它所在的 Activity 或 Fragment
Activity activity = findActivity(view.getContext());
@Nullable
private Activity findActivity(@NonNull Context context) {
if (context instanceof Activity) {
return (Activity) context;
} else if (context instanceof ContextWrapper) {
return findActivity(((ContextWrapper) context).getBaseContext());
} else {
return null;
}
}
@Nullable
private Fragment findSupportFragment(@NonNull View target, @NonNull
FragmentActivity activity) {
tempViewToSupportFragment.clear();
findAllSupportFragmentsWithViews(
activity.getSupportFragmentManager().getFragments(), tempViewToSupportFragment);
Fragment result = null;
View activityRoot = activity.findViewById(android.R.id.content);
View current = target;
while (!current.equals(activityRoot)) {
result = tempViewToSupportFragment.get(current);
if (result != null) {
break;
}
if (current.getParent() instanceof View) {
current = (View) current.getParent();
} else {
break;
}
}
tempViewToSupportFragment.clear();
return result;
}
Context 通过 Context 获取 Activity or FragmentActivity or Application Context
if (context == null) {
throw new IllegalArgumentException(“You cannot start a load on a nullContext”);
} 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);
Glide 如何实现缓存?
提供了两个内存缓存, 分别存储强弱引用弱引用的缓存: 存放正在使用的强引用的缓存: 存放没有使用的
Map<Key, ResourceWeakReference> activeEngineResources// 在
private final Map<T, Y> cache = new LinkedHashMap<>(100, 0.75f, true);// 在 LruCache 类中
查找内存缓存,
1. 先从弱引用的缓存查,
2. 没有再从强引用的缓存查,查到后从强引用缓存中移除,加入到弱引用的缓存
Engine.load() 方法
EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
if (active != null) {
cb.onResourceReady(active, DataSource.MEMORY_CACHE);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey(“Loaded resource from active resources”, startTime, key);
}
return null;
}
EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
Engine.loadFromCache() 方法
private EngineResource<?> loadFromCache(Key key, boolean isMemoryCacheable) {
if (!isMemoryCacheable) {
return null;
}
EngineResource<?> cached = getEngineResourceFromCache(key); //
if (cached != null) {
cached.acquire();
activeResources.activate(key, cached);
}
return cached;
}
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 /*isMemoryCacheable*/, true /*isRecyclable*/);
}
return result;
}
Glide 如何实现图片压缩?
Glide 实现的等比压缩,保持原图长宽比例,主要是通过原图宽高和预设的宽高设置 BitmapFactory.Options.inSampleSize
float widthPercentage = requestedWidth / (float) sourceWidth;
float heightPercentage = requestedHeight / (float) sourceHeight;
exactScaleFactor = Math.min(widthPercentage, heightPercentage);
int outWidth = round(exactScaleFactor * sourceWidth);
int outHeight = round(exactScaleFactor * sourceHeight);
int widthScaleFactor = sourceWidth / outWidth;
int heightScaleFactor = sourceHeight / outHeight;
int scaleFactor = rounding == SampleSizeRounding.MEMORY
? Math.max(widthScaleFactor, heightScaleFactor)
: Math.min(widthScaleFactor, heightScaleFactor);
int powerOfTwoSampleSize;
// BitmapFactory does not support downsampling wbmp files on platforms <= M. See b/27305903.
if (Build.VERSION.SDK_INT <= 23
&& NO_DOWNSAMPLE_PRE_N_MIME_TYPES.contains(options.outMimeType)) {
powerOfTwoSampleSize = 1;
} else {
powerOfTwoSampleSize = Math.max(1, Integer.highestOneBit(scaleFactor));
if (rounding == SampleSizeRounding.MEMORY
&& powerOfTwoSampleSize < (1.f / exactScaleFactor)) {
powerOfTwoSampleSize = powerOfTwoSampleSize << 1;
}
}
options.inSampleSize = powerOfTwoSampleSize;