javaandroidmultithreadingandroid-task

How to access result of void onComplete() of a Task


I'm working with a lib strangely designed this code basically has a Task object withonComplete() and onfail() methods, both these methods are void so I cannot use return inside them.

I have tried to use an external variable updated inside the task onComplete() and onfail()using

mytask.wait();
return value; 

with the intention to wait for the completion of the task and then return value but I get

java.lang.IllegalMonitorStateException: object not locked by thread before wait()

if I try something like

while(!mytask.isComplete(){}

to force the method to wait the completion

app totally freezes

How could I get the value at the completion of the task correctly?


Solution

  • java.lang.IllegalMonitorStateException: object not locked by thread before wait()

    You are close but you are missing some synchronization. To do wait() or notify() you need to be in a synchronized block.

    If you wanted to write a task that returned some value, I would do something like the following. Sore the result in a field, update that field inside of synchronized onComplete() or onFail() methods. Then your calling thread can use the waitForResult() method to return it once it has finished.

    public class MyTask implements Task {
        private String result;
        public synchronized void onComplete() {
            result = "it worked";
            // this is allowed because the method is synchronized
            notify();
        }
        public synchronized void onFail() {
            result = "it failed";
            // this is allowed because the method is synchronized
            notify();
        }
        public synchronized String waitForResult() {
            // a while loop is a good pattern because of spurious wakeups
            // also, it's important to realize that the job might have already
            // finished so we should always test it _before_ we wait
            while (result == null) {
                wait();
            }
            return result;
        }
    }
    

    The thread that is testing for everything to finish would then just need to do:

    String result = myTask.waitForResult();
    

    Hope this helps.