我有一个JAVA(在Android上运行)方法偶尔会因为除零而捕获ArithmeticException,尽管变量inSampleSize在循环之前设置为1并且每次只能乘以2。以下是方法。知道我在这里缺少什么吗?谢谢!
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
try {
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
} catch (ArithmeticException e) {
LogUtil.Log("ArithmeticException=" + e.getMessage() + " inSampleSize=" + inSampleSize);
Crashlytics.logException(e);
inSampleSize=1;
}
LogUtil.Log("inSampleSize="+inSampleSize);
return inSampleSize;
}
答案 0 :(得分:2)
乍一看,如果您将某个数字初始化为1
并且只能将其乘以2
,则可能永远无法获得0
的结果。但是,在while
循环的32次迭代之后,inSampleSize
的值实际上将是0
。这是因为Java忽略了int
的溢出。
这可以通过执行以下代码来证明:
int count = 0;
int inSampleSize = 1;
while (inSampleSize != 0) {
count++;
inSampleSize *= 2;
}
当inSampleSize
的值为零时,此循环将终止,此时count
为32。
那么,剩下的问题是在上述代码在什么情况下执行while
循环的32次迭代?答案是,当reqWidth
和reqHeight
都小于1
时。
所以,例如,如果你打电话:
calculateInSampleSize(options, 0, 0);
你会看到你正在描述的问题。
如果reqWidth
或reqHeight
为零,则加载位图可能没有意义,因为它不可见。但是,也许您使用View.getWidth()
和View.getHeight()
来获取宽度和高度,并且在某些情况下过早调用,在视图布局之前,这些方法可能会返回0.显然这是最后一点是猜测,如果没有看到更多的代码就无法知道,但我相信如果你在日志记录中添加reqWidth
和reqHeight
,你会发现它们不到1当发生这种情况时。
答案 1 :(得分:0)
因为height和halfHeight是int,所以你面对这个例外。
final int halfHeight = height / 2;
如果height = 1,halfHeight将为0。在你打电话的时候
halfHeight / inSampleSize
你将得到ArithmeticException,因为halfHeight为0.
解决方案:在开始操作之前,将所有度量转换为double或BigDecimal,尤其是在进行除法运算时。