The LoginActivity has two observe viewmodels; one user login, the other one fetches data from the cart, and below the two observe viewmodels, I have Toast to show the message "Finish." I am wondering why, when I click the login button, it shows the message "Finish." It should show "Login successful." Why not execute them sequentially? I want to execute code login, then check if the user is logged in, and then retrieve the cart item that the user added to the cart from the API using retrofit. Sorry for my bad English writing. Thank you in advance.
In LoginActivity onCreate method.
AlertDialog alert = createAlertDialog(this);
loginViewModel.getLoginResponseLiveData(email, password).observe(this, loginSignupResponse -> {
if(!loginSignupResponse.isError()){
User user = loginSignupResponse.getUser();
String token = loginSignupResponse.getToken();
LoginUtils.getInstance(this).saveUserInfo(user);
LoginUtils.getInstance(this).saveUserToken(token);
Toast.makeText(this, "Login successful.", Toast.LENGTH_SHORT).show();
}else{
alert.dismiss();
Toast.makeText(this, loginSignupResponse.getMessage(), Toast.LENGTH_SHORT).show();
}
});
if(LoginUtils.getInstance(this).isLoggedIn()){
String token = "Bearer " LoginUtils.getInstance(this).getUserToken();
cartViewModel.getProductsInCart(token).observe(this, cartResponse -> {
if(cartResponse != null){
List<Cart> carts = cartResponse.getCarts();
CartUtils.getInstance().setCarts(carts);
}
alert.dismiss();
});
}
Toast.makeText(this, "Finish", Toast.LENGTH_SHORT).show();
LoginViewModel
public class LoginViewModel extends ViewModel {
private final LoginRepository loginRepository;
public LoginViewModel(){
loginRepository = new LoginRepository();
}
public LiveData<LoginSignupResponse> getLoginResponseLiveData(String email, String password){
return loginRepository.getLoginResponseData(email, password);
}
}
CartViewModel
public class CartViewModel extends ViewModel {
private final CartRepository cartRepository;
public CartViewModel(){
cartRepository = new CartRepository();
}
public LiveData<CartResponse> getProductsInCart(String token){
return cartRepository.getProductsInCart(token);
}
public LiveData<CartAddResponse> addProductToCart(String token, JsonObject body){
return cartRepository.addProductToCart(token, body);
}
} LoginRepository
public class LoginRepository {
private static final String TAG = LoginRepository.class.getSimpleName();
public LiveData<LoginSignupResponse> getLoginResponseData(String email, String password){
final MutableLiveData<LoginSignupResponse> mutableLiveData = new MutableLiveData<>();
JsonObject jsonBody = new JsonObject();
jsonBody.addProperty("email", email);
jsonBody.addProperty("password", password);
RetrofitClient.getInstance().getApi().loginUser(jsonBody).enqueue(new Callback<LoginSignupResponse>() {
@Override
public void onResponse(Call<LoginSignupResponse> call, Response<LoginSignupResponse> response) {
Log.d(TAG, "onResponse: Succeeded");
LoginSignupResponse loginSignupResponse;
if(response.code() == 200){
loginSignupResponse = response.body();
}else{
String errorMessage = "Incorrect Information!";
try {
JSONObject jObjError = new JSONObject(response.errorBody().string());
errorMessage = jObjError.getString("message");
} catch (JSONException | IOException e) {
e.printStackTrace();
}
loginSignupResponse = new LoginSignupResponse(errorMessage);
}
mutableLiveData.setValue(loginSignupResponse);
}
@Override
public void onFailure(Call<LoginSignupResponse> call, Throwable t) {
Log.d(TAG, "onFailure: " t.getMessage());
}
});
return mutableLiveData;
}
}
CartRepository
public class CartRepository {
private static final String TAG = CartRepository.class.getSimpleName();
public LiveData<CartResponse> getProductsInCart(String token){
final MutableLiveData<CartResponse> mutableLiveData = new MutableLiveData<>();
RetrofitClient.getInstance().getApi().getProductsInCart(token).enqueue(new Callback<CartResponse>() {
@Override
public void onResponse(Call<CartResponse> call, Response<CartResponse> response) {
Log.d(TAG, "onResponse get: " response.code());
CartResponse cartResponse = response.body();
if(response.body() != null){
mutableLiveData.setValue(cartResponse);
}
}
@Override
public void onFailure(Call<CartResponse> call, Throwable t) {
Log.d(TAG, "onFailure get: " t.getMessage());
}
});
return mutableLiveData;
}
public LiveData<CartAddResponse> addProductToCart(String token, JsonObject body){
final MutableLiveData<CartAddResponse> mutableLiveData = new MutableLiveData<>();
RetrofitClient.getInstance().getApi().addProductToCart(token, body).enqueue(new Callback<CartAddResponse>() {
@Override
public void onResponse(Call<CartAddResponse> call, Response<CartAddResponse> response) {
Log.d(TAG, "onResponse create: " response.code());
CartAddResponse cartAddResponse = response.body();
if(cartAddResponse != null){
mutableLiveData.setValue(cartAddResponse);
}
}
@Override
public void onFailure(Call<CartAddResponse> call, Throwable t) {
Log.d(TAG, "onFailure create: " t.getMessage());
}
});
return mutableLiveData;
}
}
CodePudding user response:
LiveData.observe
is a non-blocking call, meaning that it will not block the thread it was called on, while waiting for the data that's "observed" to be available. Any code that depends on the result of observe
should be executed inside the lambda that's passed to observe
as an argument. In your case, if you need to wait for the loginSignupResponse
before proceeding to load the data, then the code should look like this:
AlertDialog alert = createAlertDialog(this);
loginViewModel.getLoginResponseLiveData(email, password).observe(this, loginSignupResponse -> {
if(!loginSignupResponse.isError()){
User user = loginSignupResponse.getUser();
String token = loginSignupResponse.getToken();
LoginUtils.getInstance(this).saveUserInfo(user);
LoginUtils.getInstance(this).saveUserToken(token);
Toast.makeText(this, "Login successful.", Toast.LENGTH_SHORT).show();
if(LoginUtils.getInstance(this).isLoggedIn()){
String token = "Bearer " LoginUtils.getInstance(this).getUserToken();
cartViewModel.getProductsInCart(token).observe(this, cartResponse -> {
if(cartResponse != null){
List<Cart> carts = cartResponse.getCarts();
CartUtils.getInstance().setCarts(carts);
}
alert.dismiss();
});
}
Toast.makeText(this, "Finish", Toast.LENGTH_SHORT).show();
} else {
alert.dismiss();
Toast.makeText(this, loginSignupResponse.getMessage(), Toast.LENGTH_SHORT).show();
}
});