我有一个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;
}

最佳答案

乍一看,如果您将一个数字初始化为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次迭代?答案是,当reqWidthreqHeight都小于1时。

因此,例如,如果您致电:
calculateInSampleSize(options, 0, 0);

您会看到您正在描述的问题。

如果reqWidthreqHeight为零,则根本不会加载位图,因为它不可见。但是,也许您正在使用View.getWidth()View.getHeight()来获取宽度和高度,并且在某些情况下调用视图的时间太早,在这些视图的布局点之前,这些方法可能返回0。显然,这最后一点是猜测,不可能知道没有看到更多代码,但是我相信,如果您在日志记录中添加了reqWidthreqHeight,那么您会发现它们小于1。

09-30 09:44