0

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?

AndreaF
  • 11,975
  • 27
  • 102
  • 168

2 Answers2

1

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.

Gray
  • 115,027
  • 24
  • 293
  • 354
0

You can create an interface, pass it to AsyncTask (in constructor), and then call method in onPostExecute()

For example:

Your interface:

public interface OnTaskCompleted{
    void onTaskCompleted();
}

Your Activity:

public class YourActivity implements OnTaskCompleted{
    // your Activity
}

And your AsyncTask:

public class YourTask extends AsyncTask<Object,Object,Object>{ //change Object to required type
    private OnTaskCompleted listener;

    public YourTask(OnTaskCompleted listener){
        this.listener=listener;
    }

    // required methods

    protected void onPostExecute(Object o){
        // your stuff
        listener.onTaskCompleted();
    }
}
Khemraj Sharma
  • 57,232
  • 27
  • 203
  • 212
  • The problem is that I need to get the result of this task in a method. The Task isn't an AsynTask but a Task object and has already onComplete() method inside It the problem is how to access the value at completion and return It since onComplete is void and cannot return value from It – AndreaF May 18 '18 at 17:46
  • Can you show your complete code, so i can understand your problem. – Khemraj Sharma May 18 '18 at 17:47
  • It's like a custom Task of the package com.google.android.gms.tasks my question how to return the result in onSuccess outside since is a void inner class and I cannot use return inside It and outside I can get uncompleted status unless if I find a way to wait task completion before the return. – AndreaF May 18 '18 at 19:57
  • while loop is not best practice for that. – Khemraj Sharma May 19 '18 at 06:35
  • while loop is not best practice for that. – Khemraj Sharma May 19 '18 at 06:36