Reputation: 41
I do a API call to a webserver and I get the ID back in the method onResponse.
Now I want to save this ID and return this id in the return of the method doLogin. How can I get that variable ID in the return statement?
This is my code:
public class LoginController {
public static String doLogin(String loginMail, String loginPassword) {
//Logging Retrofit
final HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("###URLTOAPICALL###")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
APIService service = retrofit.create(APIService.class);
Call<JsonElement> call = service.doLogin(loginMail, loginPassword);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(Call<JsonElement> call, Response<JsonElement> response) {
if (response != null) {
JSONObject obj = null;
try {
obj = new JSONObject(response.body().toString());
} catch (JSONException e) {
e.printStackTrace();
}
JSONObject setup = null;
try {
setup = obj.getJSONObject("setup");
} catch (JSONException e) {
e.printStackTrace();
}
if(setup != null) {
try {
Setup stp = new Setup();
stp.setUserId(setup.getInt("id"));
//I WANT HERE TO SAVE MY ID
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
@Override
public void onFailure(Call<JsonElement> call, Throwable t) {
Log.v("ERROR", t+"");
}
});
return "I WANT RETURN THAT ID HERE";
}
}
Upvotes: 2
Views: 7415
Reputation: 717
You can use a setter method within the onResponse method of your Retrofit call. Take an instance where I have a global variable to hold distance between two points that I get from the Google maps distance matrix API:
String final_distance;
Here's my retrofit call:
call.enqueue(new Callback<JsonObject>() {
@Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
// TODO Auto-generated method stub
JsonObject object = response.body();
String distance = object.get("rows").getAsJsonArray().get(0).getAsJsonObject().get("elements").getAsJsonArray().
get(0).getAsJsonObject().get("distance").getAsJsonObject().get("value").getAsString();
//The setter method to change the global variable
setDistance(distance);
}
@Override
public void onFailure(Call<JsonObject> call, Throwable t) {
// TODO Auto-generated method stub
}
});
This is what the setter method does:
private static void setDistance(String distance) {
final_distance = distance;
}
Since the Retrofit onResponse method is asynchronous, you will need to always first check whether the final_distance is not null before using it
Upvotes: 3
Reputation: 485
While call.execute() function is synchronous it triggers app crashes on Android 4.0 or newer and you'll get NetworkOnMainThreadException
. You have to do an async request initializing your global variable into a runnable thread. At your class name add Runnable implementation.Your getDataFunction() will look something like this:
public void getData(){
Call<JsonElement> call = service.doLogin(loginMail, loginPassword);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(Call<JsonElement> call, Response<JsonElement> response) {
if (response.isSuccessful() && response != null) {
jsonObject = response.body().toString();//initialize your global variable
}
}
@Override
public void onFailure(Call<JsonElement> call, Throwable t) {
Log.v("ERROR", t+"");
}
});
}
@Override
pulic void run(){
getDataFunction();
//here you can use your initialized variable
}
Now on your onCreate function create the run thread and start it.
Thread thread = new Thread(this);
thread.start();
This is the way it solved a similar problem of mine.
Upvotes: 1
Reputation: 8106
You can't since the Call you are requesting is async. If you want to run it in the same thread you must avoid using enqueue and use execute(). Keep in mind that you need to create a thread since you cant use Network Operations on the same thread.
You can solve it using Observables or use execute like in this case (not tested)
public static String doLogin(String loginMail, String loginPassword) {
//Logging Retrofit
final HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("###URLTOAPICALL###")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
APIService service = retrofit.create(APIService.class);
Call<JsonElement> call = service.doLogin(loginMail, loginPassword);
try {
Response response = call.execute();
if (response.isSuccessful()) {
// do your stuff and
return yourString;
}
}catch (IOException ex) {
ex.printStackTrace();
}
}
You can call it in your activity using
new Thread(new Runnable() {
@Override
public void run() {
String var = doLogin("email", "paswsord");
}
});
Take care that if you want to update your UI you need to use
runOnUiThread();
Upvotes: 0
Reputation: 3009
As retrofit is asynchronous don't return from method instead use interface callbacks.
public class LoginController {
public interface LoginCallbacks{
void onLogin(String id);
void onLoginFailed(Throwable error);
}
public static void doLogin(String loginMail, String loginPassword, final LoginCallbacks loginCallbacks) {
//Logging Retrofit
final HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("###URLTOAPICALL###")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
APIService service = retrofit.create(APIService.class);
Call<JsonElement> call = service.doLogin(loginMail, loginPassword);
call.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(Call<JsonElement> call, Response<JsonElement> response) {
if (response != null) {
JSONObject obj = null;
try {
obj = new JSONObject(response.body().toString());
} catch (JSONException e) {
e.printStackTrace();
}
JSONObject setup = null;
try {
setup = obj.getJSONObject("setup");
} catch (JSONException e) {
e.printStackTrace();
}
if(setup != null) {
try {
Setup stp = new Setup();
stp.setUserId(setup.getInt("id"));
//I WANT HERE TO SAVE MY ID
if (loginCallbacks != null)
loginCallbacks.onLogin(setup.getInt("id"));
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
@Override
public void onFailure(Call<JsonElement> call, Throwable t) {
Log.v("ERROR", t+"");
if (loginCallbacks != null)
loginCallbacks.onLoginFailed(t);
}
});
}
}
Call method:
doLogin("email", "password", new LoginCallbacks() {
@Override
public void onLogin(String id) {
}
@Override
public void onLoginFailed(Throwable error) {
}
});
Upvotes: 6