void activate(Key key, EngineResource<?> resource) {
ResourceWeakReference toPut =
new ResourceWeakReference(
key,
resource,
getReferenceQueue(),
isActiveResourceRetentionAllowed);
ResourceWeakReference removed = activeEngineResources.put(key, toPut);
if (removed != null) {
removed.reset();
}
}
这里可以看到activeResources.activate(key, resource)把EngineResource放到了弱引用中,至于lru的放置逻辑如下:
- EngineResource#release()
void release() {
if (acquired <= 0) {
throw new IllegalStateException(“Cannot release a recycled or not yet acquired resource”);
}
if (!Looper.getMainLooper().equals(Looper.myLooper())) {
throw new IllegalThreadStateException(“Must call release on the main thread”);
}
if (–acquired == 0) {
listener.onResourceReleased(key, this);
}
}
当acquired变量大于0的时候,说明图片正在使用中,也就应该放到activeResources弱引用缓存当中。而经过release()之后,如果acquired变量等于0了,说明图片已经不再被使用了,那么此时会调用listener的onResourceReleased()方法来释放资源。
- Engine#onResourceReleased()
@Override
public void onResourceReleased(Key cacheKey, EngineResource<?> resource) {
Util.assertMainThread();
activeResources.deactivate(cacheKey);
if (resource.isCacheable()) {
cache.put(cacheKey, resource);
} else {
resourceRecycler.recycle(resource);
}
}
这里首先会将缓存图片从activeResources中移除,然后再将它put到LruResourceCache当中。这样也就实现了正在使用中的图片使用弱引用来进行缓存,不在使用中的图片使用LruCache来进行缓存的功能。
接下来就是Glide的磁盘缓存,磁盘缓存简单来说就是根据Key去DiskCache中取缓存,有兴趣可以自行看一下源码。
面试官2:为什么选择Glide不选择其他的图片加载框架?
- Glide和Picasso
前者要更加省内存,可以按需加载图片,默认为ARGB_565,后者为ARGB_8888。
前者支持Gif,后者并不支持。
- Glide和Fresco
Fresco低版本有优势,占用部分native内存,但是高版本一样是java内存。
Fresco加载对图片大小有限制,Glide基本没有。
Fresco推荐使用SimpleDraweeView,涉及到布局文件,这就不得不考虑迁移的成本。
Fresco有很多native的实现,想改源码成本要大的多。
Glide提供对中TransFormation帮助处理图片,Fresco并没有。
Glide版本迭代相对较快。
Glide的几个显著的优点:
- 生命周期的管理
GLide#with
@NonNull
public static RequestManager with(@NonNull Context context) {
return getRetriever(context).get(context);
}
@NonNull
public static RequestManager with(@NonNull Activity activity) {
return getRetriever(activity).get(activity);
}
@NonNull
public static RequestManager with(@NonNull FragmentActivity activity) {
return getRetriever(activity).get(activity);
}
@NonNull
public static RequestManager with(@NonNull Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}
@Deprecated
@NonNull
public static RequestManager with(@NonNull android.app.Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}
可以看到有多个重载方法,主要对两类不同的Context进行不同的处理
-
Application Context 图片加载的生命周期和应用程序一样,肯定是我们不推荐的写法。
-
其余Context,会像当前Activity创建一个隐藏的Fragment,绑定生命周期。
以Activity为例:
@NonNull
public RequestManager get(@NonNull Activity activity) {
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else {
//判断是否是销毁状态
assertNotDestroyed(activity);
android.app.FragmentManager fm = activity.getFragmentManager();
//绑定生命周期
return fragmentGet(
activity, fm, /parentHint=/ null, isActivityVisible(activity));
}
}
具体看#fragmentGet()
@NonNull
private RequestManager fragmentGet(@NonNull Context context,
@NonNull android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,
boolean isParentVisible) {
//这就是绑定的Fragment,RequestManagerFragment
RequestManagerFragment current = getRequestManagerFragment(fm, parentHint, isParentVisible);
RequestManager requestManager = current.getRequestManager();
return requestManager;
}
接着看RequestManagerFragment
public class RequestManagerFragment extends Fragment {
@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();
}
}
关联lifeCycle相应的方法。
简单来说就是通过#with()方法根据穿过来的不同的Context绑定生命周期。
- Bitmap对象池
Glide提供了一个BitmapPool来保存Bitmap。
简单来说就是当需要加载一个bitmap的时候,会根据图片的参数去池子里找到一个合适的bitmap,如果没有就重新创建。BitMapPool同样是根据Lru算法来工作的。从而提高性能。
- 高效缓存
缓存相关可以看上文描述,内存和磁盘,磁盘缓存也提供了几种缓存策略。
1.NONE,表示不缓存任何内容
2.SOURCE,表示只缓存原始图片
3.RESULT,表示只缓存转换过后的图片(默认选项)
4.ALL, 表示既缓存原始图片,也缓存转换过后的图片
大厂面试前的复习准备
接下来分享的系统学习资源以详解各大互联网公司的 Android 常见面试题为主线,从面试的角度带你介绍必备知识点,以及该知识点在项目中的实际应用。
**帮你在现在的基础上,重新梳理和建立 Android 开发的知识体系。**无论是你短期内想提升 Android 内功实力,突破自己工作中的能力瓶颈,还是准备参加 Android 面试,都会在这份资料中有所一些收获。
从架构基础开始,分了8个模块来逐步从基础进阶到架构师的环节:
多余的话就不讲了,接下来将分享面试的一个复习路线,如果你也在准备面试但是不知道怎么高效复习,可以参考一下我的复习路线,有任何问题也欢迎一起互相交流,加油吧!
首先是超级详细得不能再详细的Android开发学习思维导图,因为图片实在是太大了,所以我就只把二级目录的内容放出来,更加详细的你们可以点击**这里**。
接下来就需要梳理知识,提升储备了!(Android移动架构师七大专题学习资源)
-
**架构师筑基必备技能:**深入Java泛型+注解深入浅出+并发编程+数据传输与序列化+Java虚拟机原理+反射与类加载+动态代理+高效IO
-
**Android高级UI与FrameWork源码:**高级UI晋升+Framework内核解析+Android组件内核+数据持久化
-
**360°全方面性能调优:**设计思想与代码质量优化+程序性能优化+开发效率优化
-
**解读开源框架设计思想:**热修复设计+插件化框架解读+组件化框架设计+图片加载框架+网络访问框架设计+RXJava响应式编程框架设计+IOC架构设计+Android架构组件Jetpack
-
**NDK模块开发:**NDK基础知识体系+底层图片处理+音视频开发
-
**微信小程序:**小程序介绍+UI开发+API操作+微信对接
Android开发除了flutter还有什么是必须掌握的吗?
相信大多数从事Android开发的朋友们越来越发现,找工作越来越难了,面试的要求越来越高了
除了基础扎实的java知识,数据结构算法,设计模式还要求会底层源码,NDK技术,性能调优,还有会些小程序和跨平台,比如说flutter,以思维脑图的方式展示在下图;
优:**设计思想与代码质量优化+程序性能优化+开发效率优化
-
**解读开源框架设计思想:**热修复设计+插件化框架解读+组件化框架设计+图片加载框架+网络访问框架设计+RXJava响应式编程框架设计+IOC架构设计+Android架构组件Jetpack
-
**NDK模块开发:**NDK基础知识体系+底层图片处理+音视频开发
-
**微信小程序:**小程序介绍+UI开发+API操作+微信对接
Android开发除了flutter还有什么是必须掌握的吗?
相信大多数从事Android开发的朋友们越来越发现,找工作越来越难了,面试的要求越来越高了
除了基础扎实的java知识,数据结构算法,设计模式还要求会底层源码,NDK技术,性能调优,还有会些小程序和跨平台,比如说flutter,以思维脑图的方式展示在下图;
[外链图片转存中…(img-g7prnKEs-1726082993057)]