Reputation: 459
This question follows on from How can I use the Retrofit response outside the OnResponse function?, but I'm not allowed to comment, so I'm asking it for myself here.
I'm trying to use the Android Studio Login template because it follows the recommended architecture, but I'm having trouble returning the Result in LoginDataSource.login. The result is trapped in the Call.enqueue function and I can't get it out to return. I've reproduced the callback suggested in the above link, but that just traps the result in a new class.
How can I access the LoggedInUser returned by my server to return to my repository?
Original attempt: user is stuck in Call.enqueue - onResponse
public class LoginDataSource {
public static Retrofit retrofit = null;
LoggedInUser user;
public Result<LoggedInUser> login(String username, String password) {
user = new LoggedInUser();
try {
// TODO: handle loggedInUser authentication
retrofit = new Retrofit.Builder()
.baseUrl("https://myserver")
.addConverterFactory(GsonConverterFactory.create())
.build();
PostEndPoint endPoint = retrofit.create(PostEndPoint.class);
Call<LoggedInUser> call = endPoint.getUser("login", username, password);
call.enqueue(new Callback<LoggedInUser>() {
@Override
public void onResponse(Call<LoggedInUser> call, Response<LoggedInUser> response) {
Log.d(TAG, "onResponse: code " + response.code());
if (response.isSuccessful()){
callback.getUser();
user = response.body();
Log.d(TAG, "onResponse: " + user); // this returns valid user data
}
}
});
Log.d(TAG, "retrofit complete:" + user.getName()); // this returns null
return new Result.Success<>(user);
}
}
}
And after implementing callback: user is stuck in GetUserResponse - getUser
public class LoginDataSource {
public static Retrofit retrofit = null;
LoggedInUser user;
public Result<LoggedInUser> login(String username, String password) {
user = new LoggedInUser();
try {
// TODO: handle loggedInUser authentication
retrofit = new Retrofit.Builder()
.baseUrl("https://myserver")
.addConverterFactory(GsonConverterFactory.create())
.build();
PostEndPoint endPoint = retrofit.create(PostEndPoint.class);
Call<LoggedInUser> call = endPoint.getUser("login", username, password);
sendLoginRequest(call, new GetUserResponse(){
@Override
public void getUser(LoggedInUser userFromResponse) {
user = userFromResponse;
}
});
Log.d(TAG, "retrofit complete:" + user.getName()); // this returns null
return new Result.Success<>(user);
}
}
private void sendLoginRequest (Call call, final GetUserResponse callback) {
call.enqueue(new Callback<LoggedInUser>() {
@Override
public void onResponse(Call<LoggedInUser> call, Response<LoggedInUser> response) {
if (response.isSuccessful()){
callback.getUser(response.body());
}
}
});
}
}
public interface GetUserResponse {
void getUser(LoggedInUser user);
}
I feel like I need to have sendLoginRequest return the user, but I can't work out how to do that. Am I heading in the right direction? Any advice is welcome.
Upvotes: 2
Views: 574
Reputation: 459
I switched to Kotlin along the way, so this may not be correct Java, but it shows the process
public class LoginDataSource {
public static Retrofit retrofit = null;
MutableLiveData<LoggedInUser> user=new MutableLiveData<>(); // changed this to LiveData so it can be observed from the viewmodel
public Result<LoggedInUser> login(String username, String password) {
user = new LoggedInUser();
try {
// TODO: handle loggedInUser authentication
retrofit = new Retrofit.Builder()
.baseUrl("https://myserver")
.addConverterFactory(GsonConverterFactory.create())
.build();
PostEndPoint endPoint = retrofit.create(PostEndPoint.class);
loggedInUser = endPoint.getUser("login", username, password);
user.postValue(loggedInUser); // updated the livedata here
}
}
}
Upvotes: 1