我的代码旨在获取原始图像,异步处理它,并让用户看到他们处理过的图像。有时,图像处理会导致OutOfMemory错误,然后我想通知用户他们的设备内存不足。
但是,当我尝试捕获错误并通知订阅者时,我遇到了崩溃。此外,当我在代码中放置断点时,正在捕获OutOfMemory错误,并且subscriber.onError(e)
行被命中,但永远不会达到onPhotoProcessingError(e)
。
以下是订阅的位置:
imageDelegate.cropBitmap(rawPhoto, cameraManager.getPictureRotationDegrees(), cameraManager.getCurrentCameraId() == Camera.CameraInfo.CAMERA_FACING_FRONT)
.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Bitmap>() {
@Override
public void onNext(Bitmap bitmap)
{
onPhotoProcessed(bitmap);
}
@Override
public void onError(Throwable e)
{
onPhotoProcessingError(e);
}
@Override
public void onCompleted()
{
}
});
以下是捕获OutOfMemory错误的代码:
public Observable<Bitmap> cropBitmap(Bitmap rawPhoto, int rotation, boolean isFrontFacing)
{
return Observable.create(new Observable.OnSubscribe<Bitmap>()
{
@Override
public void call(Subscriber<? super Bitmap> subscriber)
{
try
{
// rotates the photo so that it's portrait and cuts off the
// bottom of the photo so that we have a square photo
Bitmap rotatedSquarePhoto = PhotoUtils.rotateAndTruncateBottomOfPictureIntoSquare(rawPhoto, rotation);
rawPhoto.recycle();
// we want to mirror the image to match what the user saw when taking a selfie
if (isFrontFacing)
{
rotatedSquarePhoto = PhotoUtils.reflectAboutYAxis(rotatedSquarePhoto);
}
subscriber.onNext(rotatedSquarePhoto);
}
catch (OutOfMemoryError e)
{
subscriber.onError(e);
}
}
});
}
以下是崩溃的堆栈跟踪:
04-06 16:40:55.303 22729-22729/ E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.emersonboyd, PID: 22729
java.lang.IllegalStateException: Fatal Exception thrown on Scheduler.Worker thread.
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:62)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
Caused by: java.lang.OutOfMemoryError: Failed to allocate a 921612 byte allocation with 861608 free bytes and 841KB until OOM
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:879)
at android.graphics.Bitmap.createBitmap(Bitmap.java:856)
at android.graphics.Bitmap.createBitmap(Bitmap.java:787)
at com.emersonboyd.util.PhotoUtils.rotateAndTruncateBottomOfPictureIntoSquare(PhotoUtils.java:225)
at com.emersonboyd.delgate.ImageDelegate$2.call(ImageDelegate.java:124)
at com.emersonboyd.delgate.ImageDelegate$2.call(ImageDelegate.java:116)
at rx.Observable.unsafeSubscribe(Observable.java:8460)
at rx.internal.operators.OperatorSubscribeOn$1.call(OperatorSubscribeOn.java:94)
at rx.internal.schedulers.EventLoopsScheduler$EventLoopWorker$1.call(EventLoopsScheduler.java:169)
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:428)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:272)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:761)
任何帮助我指明正确方向的帮助都会很棒。
答案 0 :(得分:2)
这是因为OutOfMemoryError
被RxJava
视为致命错误。此类错误不会在内部被“吞没”,也不会传递给onError
回调。
以下是RxJava 1 源代码的片段。在每个内部错误处理块的开头调用此方法:
public static void throwIfFatal(Throwable t) {
if (t instanceof OnErrorNotImplementedException) {
throw (OnErrorNotImplementedException) t;
} else if (t instanceof OnErrorFailedException) {
throw (OnErrorFailedException) t;
} else if (t instanceof OnCompletedFailedException) {
throw (OnCompletedFailedException) t;
}
// values here derived from https://github.com/ReactiveX/RxJava/issues/748#issuecomment-32471495
else if (t instanceof VirtualMachineError) {
throw (VirtualMachineError) t;
} else if (t instanceof ThreadDeath) {
throw (ThreadDeath) t;
} else if (t instanceof LinkageError) {
throw (LinkageError) t;
}
}
OutOfMemoryError
是VirtualMachineError
的后代。
更多信息: https://github.com/ReactiveX/RxJava/issues/296 https://github.com/ReactiveX/RxJava/issues/748
您的问题的解决方案:抓住您的OutOfMemoryError
,但改为推送任何适当的Exception
子类。
P.S。 提示:对于您的案例,请使用Observable.fromCallable
代替Observable.create