Reputation: 812
I'm trying to make an async call using retrofit, but it is returning null. I was previously able to get a synchronous call to work just fine, but my async version is not working.
Here is the code where I make the call:
// Get the nodes from Heroku
RestAdapter restAdapter = new RestAdapter.Builder().setEndpoint(
"http://myURL.com").build();
HerokuService herokuService = restAdapter.create(HerokuService.class);
Callback<Node[]> callback = new Callback<Node[]>()
{
@Override
public void failure(RetrofitError err)
{
}
@Override
public void success(Node[] nodeArray, Response response)
{
tempNodes = nodeArray;
}
};
herokuService.nodes(callback);
// tempNodes is null here
Here is the contents of HerokuService.java
public interface HerokuService
{
@GET("/nodes")
void nodes(Callback<Node[]> callback);
}
I have already checked that there is internet connection, so I'm sure that is not the issue.
I also tried setting tempNodes
to a dummy value inside failure
but it was still null. This to me indicates that it is reaching success
but that it is being set to null there.
Any thoughts on why this is happening or what I might try to fix it? Thanks!
EDIT: I tried blocking in case I wasn't waiting long enough for the callback to return as follows:
CountDownLatch latch = new CountDownLatch(1); //Class variable
//...
Callback<Node[]> callback = new Callback<Node[]>()
{
@Override
public void failure(RetrofitError err)
{
latch.countDown();
}
@Override
public void success(Node[] nodeArray, Response response)
{
tempNodes = nodeArray;
latch.countDown();
}
};
herokuService.nodes(callback);
try
{
latch.await();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
But now it just hangs and never gets past latch.await()
. Seems like the callback is just never returning?
Upvotes: 1
Views: 1637
Reputation: 812
Figured it out. Seems like I'm not waiting for the callback to return before accessing tempNodes. I realized that I can block using a CountDownLatch as described here: https://stackoverflow.com/a/7735374/3399526 and then proceed after the callback finishes.
I had to use the sync version, and then run it on a seperate thread. This is the final working version:
//Get the nodes from heroku, and block until we get them
final CountDownLatch latch = new CountDownLatch(1);
Thread thread = new Thread(new Runnable()
{
@Override
public void run()
{
try
{
// Get the nodes from Heroku
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("http://safe-hollows-9286.herokuapp.com")
.build();
HerokuService herokuService = restAdapter.create(HerokuService.class);
tempNodes = herokuService.nodes();
}
catch (Exception e)
{
e.printStackTrace();
}
latch.countDown();
}
});
thread.start();
try
{
latch.await();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
Upvotes: 1
Reputation: 43861
At which point are you evaluating tempNodes? Since this is an asynchronous operation you have to wait until the callback is actually called. If you're waiting for the result anyway, leave out the callback and set the return value of nodes()
to Node[]
or List<Node>
.
Upvotes: 1