ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【android每日一问,复习指南

2021-09-03 22:02:12  阅读:208  来源: 互联网

标签:指南 缓存 resource 复习 Glide key activity android NonNull


截取部分源码:

@NonNull
Glide build(@NonNull Context context) {

if (memoryCache == null) {
  memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
}

if (engine == null) {
  engine =
      new Engine(
          memoryCache,
          diskCacheFactory,
          diskCacheExecutor,
          sourceExecutor,
          GlideExecutor.newUnlimitedSourceExecutor(),
          GlideExecutor.newAnimationExecutor(),
          isActiveResourceRetentionAllowed);
} 

*   memoryCache就是Glide使用的内存缓存,LruResourceCache类继承了LruCache,这部分可以自行查看一下源码。

通过上面可以看到,GLide#build()方法中实例化memoryCache作为Glide的内存缓存,并将其传给Engine作为构造器的入参。

*   Engine.class 截取部分源码

{
//生成缓存key
EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations,
resourceClass, transcodeClass, options);
//从弱应用中读取缓存
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;
}
//从LruCache中读取缓存
EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
if (cached != null) {
cb.onResourceReady(cached, DataSource.MEMORY_CACHE);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey(“Loaded resource from cache”, startTime, key);
}
return null;
}
EngineJob engineJob =
engineJobFactory.build(
key,
isMemoryCacheable,
useUnlimitedSourceExecutorPool,
useAnimationPool,
onlyRetrieveFromCache);
jobs.put(key, engineJob);

engineJob.addCallback(cb);
//开启线程池,加载图片
engineJob.start(decodeJob);

}


从上可知,Glide加载过程中使用loadFromActiveResources方法和loadFromCache方法来获取内存缓存的。

大致总结一下: 首先从弱引用读取缓存,没有的话通过Lru读取,有则取,并且加到弱引用中,如果没有会开启EngineJob进行后面的图片加载逻辑。

下面直接看之后的缓存部分代码:

*   Engine#onEngineJobComplete()

public void onEngineJobComplete(EngineJob<?> engineJob, Key key, EngineResource<?> resource) {
Util.assertMainThread();
// A null resource indicates that the load failed, usually due to an exception.
if (resource != null) {
resource.setResourceListener(key, this);

  if (resource.isCacheable()) {
    activeResources.activate(key, resource);
  }
}

jobs.removeIfCurrent(key, engineJob);

}
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中取缓存,有兴趣可以自行看一下源码。

### 为什么选择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();
//绑定生命周期

标签:指南,缓存,resource,复习,Glide,key,activity,android,NonNull
来源: https://blog.csdn.net/m0_61418455/article/details/120091081

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有