先说下我出现此问题的场景:图片列表中有部分本地图片,其余都是网络图片。在弱网环境下,期望本地图片先展示出来,而实际本地图片不一定能展示出来。
原因分析: Glide内部Decode是有个线程池的,在执行的时候会将任务丢掉线程池中(EngineJob.java):
public void start(DecodeJob<R> decodeJob) {
this.decodeJob = decodeJob;
GlideExecutor executor = decodeJob.willDecodeFromCache()
? diskCacheExecutor
: getActiveSourceExecutor();
executor.execute(decodeJob);
}
private GlideExecutor getActiveSourceExecutor() {
return useUnlimitedSourceGeneratorPool
? sourceUnlimitedExecutor : (useAnimationPool ? animationExecutor : sourceExecutor);
}
默认情况下,都用的是sourceExecutor,其在GlideBuilder中定义:
Glide build(@NonNull Context context) {
if (sourceExecutor == null) {
sourceExecutor = GlideExecutor.newSourceExecutor();
}
// 省略剩余代码
}
public static GlideExecutor newSourceExecutor() {
return newSourceExecutor(
calculateBestThreadCount(),
DEFAULT_SOURCE_EXECUTOR_NAME,
UncaughtThrowableStrategy.DEFAULT);
}
public static int calculateBestThreadCount() {
if (bestThreadCount == 0) {
bestThreadCount =
Math.min(MAXIMUM_AUTOMATIC_THREAD_COUNT, RuntimeCompat.availableProcessors());
}
return bestThreadCount;
}
故可以看出,线程池最多执行4个任务,故在弱网清空下,若先加入的是网络任务,则在线程池满了的时候,新的请求会处于阻塞状态,从而造成本地图片请求不执行的问题。
注意看getActiveSourceExecutor方法,其中有个useUnlimitedSourceGeneratorPool变量,用的线程池构造代码如下:
public static GlideExecutor newUnlimitedSourceExecutor() {
return new GlideExecutor(new ThreadPoolExecutor(
0,
Integer.MAX_VALUE,
KEEP_ALIVE_TIME_MS,
TimeUnit.MILLISECONDS,
new SynchronousQueue<Runnable>(),
new DefaultThreadFactory(
SOURCE_UNLIMITED_EXECUTOR_NAME,
UncaughtThrowableStrategy.DEFAULT,
false)));
}
故若使用此线程池,那么就不会受影响,也就能解决问题了,最终代码如下:
RequestOptions options = new RequestOptions();
options.useUnlimitedSourceGeneratorsPool(true);
final GlideRequest<Bitmap> req = GlideApp.with(App.getInstance())
.asBitmap()
.load(img)
.apply(options);