尝试在 transform() 中加载图像时 Glide 冻结
Glide freezes when trying to load image inside transform()
我需要在 Glide
加载期间转换图像。
在 transform()
方法中,我还需要加载另一个图像并将其绘制在当前图像上。所以我也在 transform()
中使用 Glide
来加载任务。我使用阻塞方法 get()
因为我需要立即获得结果并且 transform()
不在主线程中运行,这很好。
需要注意的是,代码同时加载多张图片,所有图片都要进行转换,所以所有转换过程都包括通过Glide
加载额外的图片。
我的问题是,当我连续多次使用 Glide
在 transform()
方法中并行加载图像时 - 它会阻塞代码并且无法继续工作。
代码如下:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
for (int i = 0; i < 5; i++) {
final int a = i;
Glide.with(this)
.fromResource()
.asBitmap()
.load(R.drawable.ic_non_provisioned)
.transform(new BitmapTransformation(this) {
@Override
protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
Log.d(MainActivity.class.getName(), String.format("Before load. Thread %s",
Thread.currentThread().getName()));
Bitmap bitmap = load(); // freezes here
Log.d(MainActivity.class.getName(), "After load");
return toTransform;
}
@Override
public String getId() {
return String.valueOf(a); // important for demo of bug
}
})
.into(new SimpleTarget<Bitmap>() {
@Override
public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
Log.d(MainActivity.class.getName(), "Load finished");
}
});
}
}
private Bitmap load() {
try {
return Glide.with(this)
.fromResource()
.asBitmap()
.load(R.drawable.ic_search)
.into(20, 20)
.get(); // freezes here
} catch (Exception e) {
return null;
}
}
我在控制台输出中看到的内容:
D/com.golovin.androidtest.MainActivity: Before load. Thread
fifo-pool-thread-0 D/com.golovin.androidtest.MainActivity: Before
load. Thread fifo-pool-thread-1
就是这样。 Glide
没有继续工作,我什么也没看到。顺便说一下,如果我使用 get(2, TimeUnit.SECONDS)
而不是 get()
Glide
将抛出 TimeoutException
.
我做错了什么?
您正在通过请求新图像来阻止 Glide。我想这很明显,原因如下:
.into(new SimpleTarget<Bitmap>...)
计划 5 个新负载:1、2、3、4、5
- 其中 2 个开始于
fifo-pool
(您可能有两个核心)
- 位图已加载并传递给您的转换
- 这两个转换调用
.into(20, 20)
调度另外 2 个负载:6、7
.get()
块,同时完成这两个
问题是要完成加载 6 和 7,Glide 首先必须完成前 5 个,其中 1 和 2 正在进行中,但是两个正在进行的需要 6 和 7 才能完成 ->循环。
解决方案 1
你就是不能用Glide load阻塞Glide的线程,试试翻转顺序:
....load(R.drawable.ic_search).into(new SimpleTarget(20, 20) {
@Override public void onResourceReady(Bitmap icon, GlideAnimation glideAnimation) {
for (int i = 0; i < 5; i++) {
// load others using icon passed into the transformation
}
}
});
解决方案 2
您可以启动自己的执行程序服务并安排后台任务,如下所示:
Bitmap icon = Glide.....load(R.drawable.ic_search).into(20, 20).get();
Bitmap result = Glide.....load(R.drawable.ic_non_provisioned).transform(using icon).into(Target.SIZE_ORIGINAL).get();
return result; // deliver to the UI thread somehow to be set in a view
解决方案 3
您可以简单地以同步方式加载两个位图,并在任务中将它们组合在一起,而无需 Glide 转换。如果您想重复使用一些位图,可以从 Glide.get(context).getBitmapPool()
访问池。
解决方案 4
请记住,所有这些额外的复杂性可能不值得,请考虑使用布局将一个 ImageView 放置在另一个 ImageView 之上(例如 FrameLayout
)并照常加载。
方案一比方案二和方案三方便,因为你在启动其他加载时已经有了icon
,而且你在UI线程上,所以你可以应用转换和 Glide 会将图像传送到 ImageView(如果有)。
我需要在 Glide
加载期间转换图像。
在 transform()
方法中,我还需要加载另一个图像并将其绘制在当前图像上。所以我也在 transform()
中使用 Glide
来加载任务。我使用阻塞方法 get()
因为我需要立即获得结果并且 transform()
不在主线程中运行,这很好。
需要注意的是,代码同时加载多张图片,所有图片都要进行转换,所以所有转换过程都包括通过Glide
加载额外的图片。
我的问题是,当我连续多次使用 Glide
在 transform()
方法中并行加载图像时 - 它会阻塞代码并且无法继续工作。
代码如下:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
for (int i = 0; i < 5; i++) {
final int a = i;
Glide.with(this)
.fromResource()
.asBitmap()
.load(R.drawable.ic_non_provisioned)
.transform(new BitmapTransformation(this) {
@Override
protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
Log.d(MainActivity.class.getName(), String.format("Before load. Thread %s",
Thread.currentThread().getName()));
Bitmap bitmap = load(); // freezes here
Log.d(MainActivity.class.getName(), "After load");
return toTransform;
}
@Override
public String getId() {
return String.valueOf(a); // important for demo of bug
}
})
.into(new SimpleTarget<Bitmap>() {
@Override
public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
Log.d(MainActivity.class.getName(), "Load finished");
}
});
}
}
private Bitmap load() {
try {
return Glide.with(this)
.fromResource()
.asBitmap()
.load(R.drawable.ic_search)
.into(20, 20)
.get(); // freezes here
} catch (Exception e) {
return null;
}
}
我在控制台输出中看到的内容:
D/com.golovin.androidtest.MainActivity: Before load. Thread fifo-pool-thread-0 D/com.golovin.androidtest.MainActivity: Before load. Thread fifo-pool-thread-1
就是这样。 Glide
没有继续工作,我什么也没看到。顺便说一下,如果我使用 get(2, TimeUnit.SECONDS)
而不是 get()
Glide
将抛出 TimeoutException
.
我做错了什么?
您正在通过请求新图像来阻止 Glide。我想这很明显,原因如下:
.into(new SimpleTarget<Bitmap>...)
计划 5 个新负载:1、2、3、4、5- 其中 2 个开始于
fifo-pool
(您可能有两个核心) - 位图已加载并传递给您的转换
- 这两个转换调用
.into(20, 20)
调度另外 2 个负载:6、7 .get()
块,同时完成这两个
问题是要完成加载 6 和 7,Glide 首先必须完成前 5 个,其中 1 和 2 正在进行中,但是两个正在进行的需要 6 和 7 才能完成 ->循环。
解决方案 1
你就是不能用Glide load阻塞Glide的线程,试试翻转顺序:
....load(R.drawable.ic_search).into(new SimpleTarget(20, 20) {
@Override public void onResourceReady(Bitmap icon, GlideAnimation glideAnimation) {
for (int i = 0; i < 5; i++) {
// load others using icon passed into the transformation
}
}
});
解决方案 2
您可以启动自己的执行程序服务并安排后台任务,如下所示:
Bitmap icon = Glide.....load(R.drawable.ic_search).into(20, 20).get();
Bitmap result = Glide.....load(R.drawable.ic_non_provisioned).transform(using icon).into(Target.SIZE_ORIGINAL).get();
return result; // deliver to the UI thread somehow to be set in a view
解决方案 3
您可以简单地以同步方式加载两个位图,并在任务中将它们组合在一起,而无需 Glide 转换。如果您想重复使用一些位图,可以从 Glide.get(context).getBitmapPool()
访问池。
解决方案 4
请记住,所有这些额外的复杂性可能不值得,请考虑使用布局将一个 ImageView 放置在另一个 ImageView 之上(例如 FrameLayout
)并照常加载。
方案一比方案二和方案三方便,因为你在启动其他加载时已经有了icon
,而且你在UI线程上,所以你可以应用转换和 Glide 会将图像传送到 ImageView(如果有)。