How can I return value from onResponse of Retrofit v2
onResponse
is asynchronous so it will most probably finish after revealCourtPlace
has returned.
You cannot return anything from inside onResponse
like that. You can however, pass the value up or restructure your code to work with something like Rx.
Let me explain. So, one option is to pass the string value you want up with a callback. Say you have the interface:
public interface RevealCourtPlaceCallbacks {
void onSuccess(@NonNull String value);
void onError(@NonNull Throwable throwable);
}
These are the methods that whoever wants to receive the value of your network call will have to implement. You use this for example by passing it to the method revealCourtPlace
public void revealCourtPlace(String courtID, @Nullable RevealCourtPlaceCallbacks callbacks)
{
BaseService.getInstance()
.getUniqueCourt(Session.getToken(),courtID)
.enqueue(new Callback<JsonObject>() {
@Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response)
{
JsonObject object = response.body();
boolean success = object.get("success").getAsBoolean(); //json objesinde dönen success alanı true ise
if (success)
{
JsonArray resultArray = object.get("data").getAsJsonObject().get("result").getAsJsonArray();
for (int i = 0; i < resultArray.size(); i++)
{
JsonObject jsonInfoResult = resultArray.get(i).getAsJsonObject();
String courtName=jsonInfoResult.get("name").getAsString();
if (callbacks != null)
calbacks.onSuccess(courtName);
}
}
}
@Override
public void onFailure(Call<JsonObject> call, Throwable t)
{
if (callbacks != null)
callbacks.onError(t);
}
});
}
Important things to notice: The method returns void. You pass the callbacks as an argument. These callbacks must be implemented by who's calling the method, or as an anonymous class implemented on the calling spot.
This enables you to receive the string courtName
asynchronously and not having to worry about returning a value.
There's another option where you could make your code reactive. This is a bit more work and a shift in paradigm. It also requires knowledge in Rx java. I'll leave here an example of how this can be done. Bear in mind that there are several ways of doing this.
First you should define the retrofit interface differently. The return type must now be an observable:
public interface CourtApiClient {
@GET(/*...*/)
Single<JsonObject> getUniqueCourt(/*...*/);
}
I don't really know the entire interface details of your call, but the important part here is the return type is now Single
. This is an Rx observable that emits only one item or errors. The type should also be something else than JsonObject
, but this is quite hard to tell from your code what should it be. Anyway, this will work too.
The next step is to simply return the result from your revealCourtPlace
method:
public Single<JsonObject> revealCourtPlace(String courtID, @Nullable RevealCourtPlaceCallbacks callbacks)
{
return BaseService.getInstance()
.getUniqueCourt(Session.getToken(),courtID);
}
The key difference here is that the method now returns the observable and you can subscribe to it whenever you want. This makes the flow seem synchronous although it's in fact asynchronous.
You have now the choice to either map the JsonObject
to the several strings you want, or to do the parsing in your subscriber.
Edit
Since you asked in the comments how you can call your function here's a possibility:
revealCourtPlace("some court id", new RevealCourtPlaceCallbacks() {
@Override
public void onSuccess(@NonNull String value) {
// here you use the string value
}
@Override
public void onError(@NonNull Throwable throwable) {
// here you access the throwable and check what to do
}
});
Alternatively you can make the calling class implement these callbacks and simply pass this
:
revealCourtPlace("some court id", this);