Home > database >  Why doesn't viewmodel observe in sequence?
Why doesn't viewmodel observe in sequence?

Time:06-27

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();
    }
});
  • Related