我有一些使用新的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() {
.....
}
所以我只是不确定怎么可能,位图突然没有正确的高度或宽度。我不知道异常来自哪段代码,因为报告只包括palette类中的内容。
这里有一个例外:
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+
你知道哪里不对吗?
您可能试图在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
是位图
我认为你的代码没有任何问题。我在看你发布的StackTrace。
at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:601)
at android.support.v7.graphics.Palette.scaleBitmapDown(Palette.java:282)
如果您查看Palette.java的源代码,您将发现在方法scaleBitmapDown(Bitmap bitmap)
中编写的缩放逻辑。如果您的"位图"小于100px,则不进行缩放。但是,如果您的"位图"大于100px,则调用Bitmap.createScaledBitmap()
。现在这个方法抛出IllegalArgumentException
如果宽度或高度<</p> 0;
所以你传递的位图不具有零宽度,因为如果是这种情况,你根本就不会到达Bitmap.createScaledBitmap()
方法。话虽如此,我不确定真正的原因是什么。
Palette.java
的源代码。问题与并发性问题有关:因为您正在使用'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() {
.....
}