尝试在transform()

时间:2016-02-03 17:13:37

标签: java android multithreading android-glide

我需要在Glide加载期间转换图像。

transform()内部方法中,我还需要加载另一个图像并将其绘制在当前图像上。所以我也在Glide内使用transform()进行加载任务。我使用阻塞方法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:加载前。线   fifo-pool-thread-0 D / com.golovin.androidtest.MainActivity:之前   加载。线程fifo-pool-thread-1

这就是全部。 Glide没有继续工作,我什么也没看到。顺便说一句,如果我使用get(2, TimeUnit.SECONDS)代替get() Glide,则会抛出TimeoutException

我做错了什么?

1 个答案:

答案 0 :(得分:4)

您通过请求新图片来阻止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来完成 - &gt;周期。

解决方案1 ​​

你只是无法用Glide加载阻止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定位在另一个之上(例如,使用FrameLayout)并加载为ususal。

解决方案1比解决方案2和3更方便,因为当您启动其他加载并且您已经在UI线程上时已经有icon,因此您可以应用转换和Glide将将图像传送到ImageView(如果有的话)。