【问题标题】:android.support.v7.graphics.Palette width and height must be > 0android.support.v7.graphics.Palette 宽度和高度必须 > 0
【发布时间】:2015-09-28 18:32:20
【问题描述】:

我有一些代码使用新的 Palette 类,我在 Crashlytics 上收到这些崩溃报告,上面写着 width and height must be > 0。奇怪的是,这就是我调用调色板代码的方式:

if( bitmap == null || bitmap.getHeight() <= 0 || bitmap.getWidth() <= 0){
   //do something
}else{
   Palette.Builder(bitmap).generate(new Palette.PaletteAsyncListener() {
.....
}

所以我只是不确定位图怎么可能突然没有正确的高度或宽度。我不知道异常来自我的哪一段代码,因为报告只包含调色板类中的内容。

这是一个例外:

java.lang.RuntimeException: An error occured while executing doInBackground()
       at android.os.AsyncTask$3.done(AsyncTask.java:300)
       at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
       at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
       at java.util.concurrent.FutureTask.run(FutureTask.java:242)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
       at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.IllegalArgumentException: width and height must be > 0
       at android.graphics.Bitmap.createBitmap(Bitmap.java:815)
       at android.graphics.Bitmap.createBitmap(Bitmap.java:794)
       at android.graphics.Bitmap.createBitmap(Bitmap.java:725)
       at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:601)
       at android.support.v7.graphics.Palette.scaleBitmapDown(Palette.java:282)
       at android.support.v7.graphics.Palette.access$100(Palette.java:67)
       at android.support.v7.graphics.Palette$Builder.generate(Palette.java:557)
       at android.support.v7.graphics.Palette$Builder$1.doInBackground(Palette.java:623)
       at android.support.v7.graphics.Palette$Builder$1.doInBackground(Palette.java:620)
       at android.os.AsyncTask$2.call(AsyncTask.java:288)
       at java.util.concurrent.FutureTask.run(FutureTask.java:237)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
       at java.lang.Thread.run(Thread.java:818)

我正在使用来自 com.android.support:palette-v7:23+ 的 Palette 类

有什么想法可能是错的吗?

【问题讨论】:

  • 你真的确定位图有什么东西,甚至正在显示吗?调色板必须分析图像,几毫秒后,你会得到颜色。
  • 嗯,我只收到 Crashlytics 的错误,从来没有发生在我身上。但在调用调色板代码之前,我正在检查 null 和大小。
  • 应用永远不会崩溃?你可以重现这个问题吗?如果不是...也许某些用户使用的是低端智能手机并且任务花费了太多时间并且调色板找到空值(在调色板而不是位图上崩溃)
  • 该应用程序从来没有因为这个问题而崩溃过。我不确定为什么在调色板运行时位图会变为空,调色板不会引用它吗?也许位图正在被回收,但错误会是关于它被回收吗?
  • 我猜这个错误是由监听器内部的代码引起的。您能否提供更多代码(示例中的点在哪里)?

标签: android android-support-library android-palette


【解决方案1】:

您可能试图在 UI 元素实际添加到布局之前访问它的宽度和高度。

这就是为什么你一直得到宽度和高度等于 0,因为元素实际上并不存在。

使用ViewTreeObserver http://developer.android.com/reference/android/view/ViewTreeObserver.html

    myView.getViewTreeObserver().addOnPreDrawListener(
            new ViewTreeObserver.OnPreDrawListener() {
                public boolean onPreDraw() {

                        int finalHeight = myView.getMeasuredHeight();
                        int finalWidth = myView.getMeasuredWidth();
                        // Do your work here


                    return true;
                }
            });

myView 将是您的位图

【讨论】:

  • 我不想访问它,Palette 类是。在调用Palette 类之前,我正在检查宽度和高度以及空值。我无法更改Palette 代码,那么如何确保不会发生这种情况?
  • 调用 TreeObserver 中的 Palette 类。这样,在调色板类尝试访问位图之前就定义了位图。
  • 在调用调色板代码之前,我实际上没有将这些位图加载到的视图。在我知道调色板颜色后,我将它们加载到视图中。这对我的大多数用户来说都很好,每天 20k 的用户中只有 4 到 5 次崩溃。
【解决方案2】:

我认为您的代码没有任何问题。我正在查看您发布的 StackTrace。

at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:601)
at android.support.v7.graphics.Palette.scaleBitmapDown(Palette.java:282)

如果你查看Palette.java的源代码,你会发现在方法scaleBitmapDown(Bitmap bitmap)中写的缩放逻辑。如果您的“位图”小于 100 像素,则不进行缩放。但是,如果您的“位图”大于 100 像素,则调用 Bitmap.createScaledBitmap()。现在这个方法抛出 IllegalArgumentException 如果宽度或高度

因此,您传递的位图宽度不为零,因为如果是这种情况,您将根本无法使用Bitmap.createScaledBitmap() 方法。话虽如此,我不确定真正的原因可能是什么。尝试查看您正在使用的确切 Palette.java 的源代码。

【讨论】:

  • 当我点击粘贴的堆栈跟踪时,Android Studio 给我的调色板代码有点不同,但它确实有你看到的相同检查。我想如果检查和缩放之间的位图发生了什么事,那将是唯一的可能性。
  • 我的猜测也是。崩溃是否发生在某个特定设备的特定版本上?如果是这种情况,那么操作系统版本代码可能存在错误。但无论如何,我认为你不会对此采取任何行动。
【解决方案3】:

问题与并发问题有关:由于您以'async'方式使用Palette,因此当您调用

Palette.Builder(bitmap).generate(new Palette.PaletteAsyncListener()

您的位图有效,但当Palette 在其自己的异步逻辑中使用该位图时,该位图可能为空或不再有效(由于并发操作)。

这个问题有一个简单的解决方法:因为您不需要高分辨率图像来提取关键颜色,只需提供从原始图像创建的低分辨率位图:

if( bitmap == null || bitmap.getHeight() <= 0 || bitmap.getWidth() <= 0){
   //do something
}else{
   //This resized bitmap is just an example: you should keep your bitmap
   //aspect ratio, and keep width and height < 100
   Bitmap resizedBitmap = Bitmap.createScaledBitmap(myBitmap, 100, 100, false); 
   Palette.Builder(resizedBitmap).generate(new Palette.PaletteAsyncListener() {
.....
}

【讨论】:

  • 有趣的想法,我会试试的。谢谢。
  • @mntgoat 不要忘记在调整大小的位图中保持纵横比,否则您可能会得到错误的键颜色(我在示例中强制使用 100x100px)
  • 是的,我是。我实际看到的 Palette 类代码使用 192 作为最小值。
  • @mntgoat 您应该在宽度和高度上使用
  • 我将在赏金到期之前奖励你,但我还不知道这是否是正确的答案。我会将它发布给我的测试版用户,如果几天后我不再出现崩溃,我会将其标记为正确答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-10
相关资源
最近更新 更多