Bitmap.createBitmap 得到 的bitmap 不一定是新的bitmap

File tempFile = null;
try {
    Bitmap bitmap = BitmapUtils.createThumbnail(imagePath, 1080, 1080 * 1920);
    if (bitmap != null) {
        Bitmap tmp = BitmapUtils.rotateImg(BitmapUtils.getOrientation(imagePath), bitmap);
        LogUtil.d("111 tmp = " + tmp + " ,  bitmap = " + bitmap + "  isRecycled = " + tmp.isRecycled());
        if (tmp != null) {
            bitmap.recycle();
            LogUtil.d("222 tmp = " + tmp + " ,  bitmap = " + bitmap + "  isRecycled = " + tmp.isRecycled());
            bitmap = tmp;
        }
        LogUtil.d("tmp = " + tmp + "  isRecycled = " + tmp.isRecycled());
    }

    if (bitmap != null) {
        LogUtil.d("bitmap = " + bitmap + "  , isRecycled " + bitmap.isRecycled());
        File tempDir = StorageUtils.getIndividualCacheDirectory(context, Config.IMAGE_TEMP_DIR_NAME);
        tempFile = File.createTempFile("img_", ".jpg", tempDir);
        bitmap.compress(CompressFormat.JPEG, 70, new FileOutputStream(tempFile));
        bitmap.recycle();
    }
} catch (Throwable e) {
    e.printStackTrace();
    tempFile = null;
}

上面的代码看似 没有什么问题, 但是在执行的时候会抛出 异常 
在执行 bitmap.compress(CompressFormat.JPEG, 70, new FileOutputStream(tempFile)); 方法的时候
会抛出如下异常: 
java.lang.IllegalStateException: Can't compress a recycled bitmap
12-23 15:30:14.009 30211-30211/com.zuiapps.deer W/System.err:     at android.graphics.Bitmap.checkRecycled(Bitmap.java:347)
12-23 15:30:14.009 30211-30211/com.zuiapps.deer W/System.err:     at android.graphics.Bitmap.compress(Bitmap.java:999)
12-23 15:30:14.009 30211-30211/com.zuiapps.deer W/System.err:     at com.zuiapps.deer.common.utils.ImageUtils.compressImage(ImageUtils.java:75)
12-23 15:30:14.009 30211-30211/com.zuiapps.deer W/System.err:     at com.zuiapps.deer.publish.presenter.PublishPresenter.uploadImages(PublishPresenter.java:110)
12-23 15:30:14.009 30211-30211/com.zuiapps.deer W/System.err:     at com.zuiapps.deer.publish.presenter.PublishPresenter.cycleUpload(PublishPresenter.java:163)
12-23 15:30:14.009 30211-30211/com.zuiapps.deer W/System.err:     at com.zuiapps.deer.publish.presenter.PublishPresenter.access$700(PublishPresenter.java:36)
12-23 15:30:14.009 30211-30211/com.zuiapps.deer W/System.err:     at com.zuiapps.deer.publish.presenter.PublishPresenter$3.complete(PublishPresenter.java:148)
12-23 15:30:14.009 30211-30211/com.zuiapps.deer W/System.err:     at com.qiniu.android.storage.ResumeUploader$1.complete(ResumeUploader.java:79)
12-23 15:30:14.009 30211-30211/com.zuiapps.deer W/System.err:     at com.qiniu.android.storage.ResumeUploader$2.complete(ResumeUploader.java:202)
12-23 15:30:14.009 30211-30211/com.zuiapps.deer W/System.err:     at com.qiniu.android.http.HttpManager$2.complete(HttpManager.java:170)
12-23 15:30:14.009 30211-30211/com.zuiapps.deer W/System.err:     at com.qiniu.android.http.ResponseHandler.onSuccess(ResponseHandler.java:156)
12-23 15:30:14.009 30211-30211/com.zuiapps.deer W/System.err:     at com.loopj.android.http.AsyncHttpResponseHandler.handleMessage(AsyncHttpResponseHandler.java:351)
12-23 15:30:14.009 30211-30211/com.zuiapps.deer W/System.err:     at com.loopj.android.http.AsyncHttpResponseHandler$ResponderHandler.handleMessage(AsyncHttpResponseHandler.java:510)
12-23 15:30:14.009 30211-30211/com.zuiapps.deer W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:102)
12-23 15:30:14.009 30211-30211/com.zuiapps.deer W/System.err:     at android.os.Looper.loop(Looper.java:139)
12-23 15:30:14.009 30211-30211/com.zuiapps.deer W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:5267)
12-23 15:30:14.009 30211-30211/com.zuiapps.deer W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
12-23 15:30:14.009 30211-30211/com.zuiapps.deer W/System.err:     at java.lang.reflect.Method.invoke(Method.java:372)
12-23 15:30:14.009 30211-30211/com.zuiapps.deer W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:950)
12-23 15:30:14.009 30211-30211/com.zuiapps.deer W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:745)

说 bitmap 已被recycle掉了 
但是我们看 上面的代码:
Bitmap tmp = BitmapUtils.rotateImg(BitmapUtils.getOrientation(imagePath), bitmap);
LogUtil.d("111 tmp = " + tmp + " ,  bitmap = " + bitmap + "  isRecycled = " + tmp.isRecycled());
if (tmp != null) {
    bitmap.recycle();
    LogUtil.d("222 tmp = " + tmp + " ,  bitmap = " + bitmap + "  isRecycled = " + tmp.isRecycled());
    bitmap = tmp;
}



可以看到 recycle 掉的是原来的bitmap,  不是刚刚创建的 tmp
然后 bitmap 就马上 指向 tmp 这个bitmap了

看起来好想没什么问题,
但是 通过打印出来的log可以看出

111 tmp = android.graphics.Bitmap@315901c2 ,  bitmap = android.graphics.Bitmap@315901c2  isRecycled = false
12-23 15:42:07.838 10655-10748/com.zuiapps.deer D/LogUtil: 222 tmp = android.graphics.Bitmap@315901c2 ,  bitmap = android.graphics.Bitmap@315901c2  isRecycled = true
12-23 15:42:07.838 10655-10748/com.zuiapps.deer D/LogUtil: tmp = android.graphics.Bitmap@315901c2  isRecycled = true
12-23 15:42:07.838 10655-10748/com.zuiapps.deer D/LogUtil: bitmap = android.graphics.Bitmap@315901c2  , isRecycled true


有些情况  tmp = android.graphics.Bitmap@315901c2 ,  bitmap = android.graphics.Bitmap@315901c2 是同一个对象 
查看  rotateImg 方法 发现里面调用了:Bitmap.createBitmap 方法
有些情况  tmp = android.graphics.Bitmap@315901c2 ,  bitmap = android.graphics.Bitmap@315901c2 是同一个对象 
查看  rotateImg 方法 发现里面调用了:Bitmap.createBitmap 方法
public static Bitmap rotateImg(int degree, Bitmap bitmap) {
   Matrix matrix = new Matrix();
   matrix.postRotate(degree);
   return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}

在看 Bitmap.createBitmap 发现 有些情况下 确实是会返回 原bitmap的 

public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height,
        Matrix m, boolean filter) {

    checkXYSign(x, y);
    checkWidthHeight(width, height);
    if (x + width > source.getWidth()) {
        throw new IllegalArgumentException("x + width must be <= bitmap.width()");
    }
    if (y + height > source.getHeight()) {
        throw new IllegalArgumentException("y + height must be <= bitmap.height()");
    }

    // check if we can just return our argument unchanged
    if (!source.isMutable() && x == 0 && y == 0 && width == source.getWidth() &&
            height == source.getHeight() && (m == null || m.isIdentity())) {
        return source;
    }
    …
}


所以要注意  Bitmap.createBitmap 得到 的bitmap 不一定是新的bitmap

不能随意 recycle



你可能感兴趣的:(Android)