Tom Oakley February 2016

Return value from inner class in a method

I am building a Login system for an Android app. I am using OkHttp to connect to my server and get a JSON response.

I have defined a class with the login return data (right now just a true/false response based on whether the user exists in the database), and then written the code to connect to the server, as shown below:

class UserLogin {
    boolean status;

    public void setStatus(boolean status) {
        this.status = status;
    }

    public boolean getStatus() {
        return status;
    }
}

public class ClientServerInterface {

    OkHttpClient client = new OkHttpClient();

    boolean login(Request request) {
        final Gson gson = new Gson();
        client.newCall(request).enqueue(new Callback() {
            UserLogin login;
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                login = gson.fromJson(response.body().charStream(), UserLogin.class);
                login.setStatus(login.status);
            }
        });
        // need to return the boolean response (status) here
    }
}

The code which passes the Request variable to the login method works perfectly. I want login to return a boolean response so that I can pass that to other methods in other classes.

However, because the UserLogin object is defined in the callback I can't access it in the parent method. I have made a getStatus method but not sure how to use it properly to get the status in the main login method.

Answers


Blackbelt February 2016

The code which passes the Request variable to the login method works perfectly. I want login to return a boolean response so that I can pass that to other methods in other classes.

you can't. enqueue executes the code in Async way. You don't know when the callback is invoked. What you could do is to add the Callback as parameter to your login method. E.g.

 boolean login(Request request, final Callback callback) {

and either pass it to enqueue,

client.newCall(request).enqueue(callback);

or call the callback manually. E.g.

@Override
public void onResponse(Call call, Response response) throws IOException {
      if (callback != null) {
           callback.onResponse(call, response);
      }
}

in both cases the caller of login will receive the callback on the provided object and, accordingly to the content it receives, can decide wha actions undertake


Andy Turner February 2016

You can do this using a SynchronousQueue:

final SynchronousQueue<Boolean> queue = new SynchronousQueue<>();
client.newCall(request).enqueue(new Callback() {
        UserLogin login;
        @Override
        public void onFailure(Call call, IOException e) {
          queue.put(false);
        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {
          queue.put(true);
        }
    });
return queue.take();


svasa February 2016

Add loginStatus variable to class like below and one more to indicate login operation completion.

public class ClientServerInterface {

    OkHttpClient client = new OkHttpClient();
    private  boolean loginStatus = false;
    private boolean isLoginOperationDone = false;
    boolean login(Request request) {
        final Gson gson = new Gson();
        client.newCall(request).enqueue(new Callback() {
            UserLogin login;
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                login = gson.fromJson(response.body().charStream(), UserLogin.class);
                loginStatus = login.setStatus(login.status);
                isLoginOperationDone = true;
            }
        });
        // need to return the boolean response (status) here
        while( !isLoginOperationDone )
        {
           //not to do anything.
        }
        return loginStatus;
    }
}

Note that this might be a little hacky but will do solve your problem.


Crew Peace February 2016

The way to go is with AsyncTask. Override the doInBackground method to perform the http requests and get the result by overriding the onPostExecute method.

Read more here: http://developer.android.com/reference/android/os/AsyncTask.html

An even better way to go is to run a background Service for all your API calls.

Post Status

Asked in February 2016
Viewed 1,007 times
Voted 8
Answered 4 times

Search




Leave an answer