Jeet.Deir Jeet.Deir - 2 months ago 25
Java Question

Exception thrown on Scheduler.Worker thread. Add `onError` handling

I was trying some code and here is the exception I get:

Process: in.ddas.pretense, PID: 8249
java.lang.IllegalStateException: Exception thrown on Scheduler.Worker thread. Add `onError` handling.
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:60)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)
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: rx.exceptions.OnErrorNotImplementedException: Can't create handler inside thread that has not called Looper.prepare()
at rx.internal.util.InternalObservableUtils$ErrorNotImplementedAction.call(InternalObservableUtils.java:386)
at rx.internal.util.InternalObservableUtils$ErrorNotImplementedAction.call(InternalObservableUtils.java:383)
at rx.internal.util.ActionSubscriber.onError(ActionSubscriber.java:44)
at rx.observers.SafeSubscriber._onError(SafeSubscriber.java:157)
at rx.observers.SafeSubscriber.onError(SafeSubscriber.java:120)
at rx.exceptions.Exceptions.throwOrReport(Exceptions.java:204)
at rx.observers.SafeSubscriber.onNext(SafeSubscriber.java:144)
at rx.internal.operators.OperatorSubscribeOn$1$1.onNext(OperatorSubscribeOn.java:53)
at rx.internal.operators.OperatorTake$1.onNext(OperatorTake.java:77)
at rx.internal.operators.OnSubscribeTimerPeriodically$1.call(OnSubscribeTimerPeriodically.java:52)
at rx.Scheduler$Worker$1.call(Scheduler.java:134)
at rx.internal.schedulers.EventLoopsScheduler$EventLoopWorker$2.call(EventLoopsScheduler.java:187)
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422) 
at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152) 
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265) 
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.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:200)
at android.os.Handler.<init>(Handler.java:114)
at in.ddas.pretense.GoogleCloudActivity.PredictionEngine(GoogleCloudActivity.java:198)
at in.ddas.pretense.GoogleCloudActivity.lambda$onClick$0(GoogleCloudActivity.java:176)
at in.ddas.pretense.GoogleCloudActivity$$Lambda$1.call(Unknown Source)
at rx.internal.util.ActionSubscriber.onNext(ActionSubscriber.java:39)
at rx.observers.SafeSubscriber.onNext(SafeSubscriber.java:139)
at rx.internal.operators.OperatorSubscribeOn$1$1.onNext(OperatorSubscribeOn.java:53) 
at rx.internal.operators.OperatorTake$1.onNext(OperatorTake.java:77) 
at rx.internal.operators.OnSubscribeTimerPeriodically$1.call(OnSubscribeTimerPeriodically.java:52) 
at rx.Scheduler$Worker$1.call(Scheduler.java:134) 
at rx.internal.schedulers.EventLoopsScheduler$EventLoopWorker$2.call(EventLoopsScheduler.java:187) 
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55) 
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422) 
at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152) 
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265) 
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) 


Here is the code for the same:

try {
kf.initFilter();
kg.initFilter();
Observable.interval(1, TimeUnit.SECONDS)
.take(5)
// switch execution into main thread
.subscribeOn(AndroidSchedulers.mainThread())
.subscribe(t -> {
PredictionEngine(1);
});
} catch (Exception e) {
e.printStackTrace();
}

private void PredictionEngine(int delay) throws Exception {

final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
enableStrictMode();
String val = null;
try {
if (tHighPass == 0 && tLowPass == 0 && tKalman == 1) {
//Magic
} else {
//Magic
}

} catch (Exception e) {
e.printStackTrace();
}
enableStrictMode();
side_output.append(val + "\n");
new DropboxTask(side_output, "Result", val).execute();
}
}, delay);
}


I am essentially trying to loop run the
PredictionEngine(int);
function a certain number of time without blocking the main thread, with a certain delay.

Where am I doing it wrong?

Thanks!

Answer

Handler's default constructor uses the Looper instance for the current thread. If you intend on your code being run on the main thread, and your handler is being initialized in a thread other than the main, you'll need to specify the Looper for the handler to use. This can be accomplished using

Handler h = new Handler(Looper.getMainLooper());