Toast message inside MutableLiveData.observe() working repeatedly

Tags: , , ,



I have a register form and ı want to show a message to the user based on signed up successfully or not.I store that message in my view model which has a mutable live data object to store that message and observing that object from my activity.My problem is when ı click to the register button first time it works normally,showing Toast with my message as expected but when ı click that button again Toast message show my message two times.I really didn’t understand what’s wrong with my code.Here is my code.

RegisterActivity

  mViewModel = new ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication())).get(RegisterActivityViewModel.class);
  mRegisterBtn.setOnClickListener(v -> {
        register();
    }); 
   private void register() {
    if (!GenericMethods.checkInputField(mKadi) || !GenericMethods.checkInputField(mEmail)
            || !GenericMethods.checkInputField(mPAss)) {
        Toast.makeText(this, "Alanlar boş geçilemez", Toast.LENGTH_SHORT).show();
        return;
    }
    signup();
}
    private void signup(){
    kAdi = mKadi.getText().toString().trim();
    email = mEmail.getText().toString().trim();
    parola = mPAss.getText().toString().trim();
    parolaTekrari = mValidpass.getText().toString().trim();
    il=mIlTv.getText().toString().trim();
    ilce=mIlceTv.getText().toString().trim();
    getRadioValue(mRadioGroup);
    üniversite=mUniTv.getText().toString().trim();
    User user = new User(kAdi,email,parola,cinsiyet,il,ilce,üniversite);
    mViewModel.signup(user);
    mViewModel.signupData.observe(this,status ->{
       Toast.makeText(RegisterActivity.this, status, Toast.LENGTH_SHORT).show();
   });
}

RegisterActivityViewModel

public MutableLiveData<String> signupData = new MutableLiveData<>();

private String statusString=null;

public void fetchFromRemote() {
    isLoading.setValue(true);
    disposable.add(RetroService.getInstance().getIller()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeWith(new DisposableSingleObserver<List<Response>>() {
                @Override
                public void onSuccess(@NonNull List<Response> responses) {
                    isLoading.setValue(false);
                    adresList.setValue(responses);
                }
                @Override
                public void onError(@NonNull Throwable e) {
                    isLoading.setValue(false);
                }
            }));
}

public void signup(User user) {
    Repo.getInstance().signup(user)
            .enqueue(new Callback<Void>() {
                @Override
                public void onResponse(Call<Void> call, retrofit2.Response<Void> response) {

                    if (response.code() == 200) {
                    statusString="Success!";
                    } else if (response.code() == 400) {
                    statusString="email already exists";
                    }
                    signupData.setValue(statusString);
                }
                @Override
                public void onFailure(Call<Void> call, Throwable t) {
                    signupData.setValue(t.getMessage());
                }
            });

}

@Override
protected void onCleared() {
    super.onCleared();
    disposable.clear();
}

Answer

Because the “register” function creates a new observer everytime it gets called. This is the observer:

Observer<String> signupDataObserver = status -> {
    Toast.makeText(RegisterActivity.this, status, Toast.LENGTH_SHORT).show();
}

Everytime the button get clicked the function add a new observer on the MutableLiveData “signUpData”:

mViewModel.signupData.observe(this, signupDataObserver);

So if you move the “observe” function into the “OnCreateView” event the problem should be solved, because the fragment will register only 1 observer when the view gets created and not when the button gets clicked. Another option would be to delete the observer after the toast message has been delivered:

Observer<String> signupDataObserver = status -> {
    Toast.makeText(RegisterActivity.this, status, Toast.LENGTH_SHORT).show();
    mViewModel.signupData.removeObserver(signupDataObserver);
}

mViewModel.signupData.observe(this, signupDataObserver);


Source: stackoverflow