Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to return value from anonymous class?

Tags:

java

I have the following code.

As you can see the method postTestResults should return a Boolean.

Now the problem is that in postTestResults I create a inner class AsyncHttpResponseHandler and I override onSuccess and onFailure to get the result of the AsyncHttpResponseHandler.

BUT if I put return true in onSuccess and onFailure obviously it does not work, because onSuccess and onFailuremust return void.

Please how do I cope with such a scenario?

public static Boolean postTestResults(DBManager db, String mDeviceId,
    String mFirmwareVer, String mJobNo, int mTestType, Activity activity) {

    MyRestClient.post(possibleEmail, device, results, new AsyncHttpResponseHandler() {

        @Override
        public void onSuccess(int arg0, Header[] arg1, byte[] arg2) {
            return true; // does not work!              
        }

        @Override
        public void onFailure(int arg0, Header[] arg1, byte[] arg2, Throwable arg3) {
            // TODO Auto-generated method stub

        }
    });

    return null;
}

enter image description here

Thanks

like image 352
Lisa Anne Avatar asked Aug 26 '14 08:08

Lisa Anne


3 Answers

After calling MyRestClient.post there still is no information available. At some time in the future onSuccess or onFailure is called. This asynchrone behaviour is intended, as you otherwise would have to wait for the a communication trip.

Do not return anything, or maybe true. And do the processing entirely differently, handle the logic by calling something in onSuccess/onFailure.


You could force a wait on the result (absolutely horrible) by:

final Semaphore semaphore = new Semaphore(0);
final AtomicBoolean succeeded = new AtomicBoolean();

MyRestClient.post(possibleEmail, device, results, new AsyncHttpResponseHandler() {

    @Override
    public void onSuccess(int arg0, Header[] arg1, byte[] arg2) {
        succeeded.set(true);
        semaphore.release();
    }

    @Override
    public void onFailure(int arg0, Header[] arg1, byte[] arg2, Throwable arg3) {
        succeeded.set(false);
        semaphore.release();
    }
});

semaphore.aquire();
return succeeded.get();

After calling the posting, the semaphore halts the current thread's execution (because of 0 permits in its constructor). When a callback is done (onSuccess/onFailure) a result is set (succeeded).

The local variables must be (effectively) final, so their object does not change. This is as the callbacks are in another thread, and the objects referenced in the callbacks are actual copies. So for understanding the must be final. The result however must be written to, hence a value holder, internal state of a final object must be used. Hence the AtomicBoolean, as a final boolean cannot be written to.

By the way, Boolean as result if an object wrapper (Boolean.TRUE, FALSE or null), boolean seems more appropriate.

like image 182
Joop Eggen Avatar answered Oct 27 '22 12:10

Joop Eggen


In your code example you use annonymous class not inner.

Annonymous class does not differ from regular classes. Its a syntax sugar that allow you to implement interfaces in place (without declaring class name, javac will do this for you).

In your case you should throw an exception in method onFailure order by interrupt the execution of code.

Because you deal with asynchronic call, you do not know when the code will be executed. There fore the task you wan to perform on success should be invoked from method onSuccess or the application should wait in some place for the result of the call back.

like image 4
Damian Leszczyński - Vash Avatar answered Oct 27 '22 13:10

Damian Leszczyński - Vash


You can add a system like that :

public class MyAsync extends AsyncHttpResponseHandler{

    private final MyAsyncState state;

    public MyAsync(MyAsyncState state){
        this.state = state;
    }


    public void onSuccess(......){
        this.state.setResult(true);
    }

    public void onFailure(.....){
        this.state.setResult(false);
    }

}

An the class MyAsyncState :

public class MyAsyncState{

    private Boolean state;

    public void setResult(boolean b){
        this.state = b;
        doIt();
    }

    private void doIt(){
        // do what you want 
        // show popup for example
    }
}
like image 2
cyril wirth Avatar answered Oct 27 '22 13:10

cyril wirth