2

I am trying to learn about data binding I have my CreditCardViewModel class which is bind in my fragment as follows

public class CreditCardValidatorFragment extends Fragment {

    private CreditCardViewModel cardViewModel;
    private CcValidateFragmentBinding binding;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        binding = DataBindingUtil.inflate(inflater, R.layout.cc_validate_fragment, container, false);
        return binding.getRoot();
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        cardViewModel = ViewModelProviders.of(this).get(CreditCardViewModel.class);
        binding.setCreditCardViewModel(cardViewModel);
        binding.submitButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Navigation.findNavController(view).navigate(CreditCardValidatorFragmentDirections.actionMainFragmentToSecondFragment("Arvinder"));
            }
        });
        //required to update UI with Live data
        binding.setLifecycleOwner(this);

    }

}
public class CreditCardViewModel extends ViewModel {
    private MutableLiveData<String> firstName = new MutableLiveData<>();
    private MutableLiveData<String> lastName = new MutableLiveData<>();
    private MutableLiveData<Long> ccNumber = new MutableLiveData<>();
    private MutableLiveData<Integer> ccType = new MutableLiveData<>();
    private MutableLiveData<String> exp = new MutableLiveData<>();
    private MutableLiveData<Integer> cvv = new MutableLiveData<>();

    public String getFirstName() {
        return firstName.getValue();
    }

    public String getLastName() {
        return lastName.getValue();
    }

    public Long getCcNumber() {
        return ccNumber.getValue().longValue();
    }

    public Integer getCcType() {
        return ccType.getValue();
    }

    public String getExp() {
        return exp.getValue();
    }

    public Integer getCvv() {
        return cvv.getValue();
    }

    public void onCvvTextChanged(CharSequence text) {
        cvv.setValue(Integer.valueOf(text.toString()));
    }

    public void onFirstNameChanged(CharSequence text) {
        firstName.setValue(text.toString());
    }

    public void onLastNameChanged(CharSequence text) {
        lastName.setValue(text.toString());
    }

    public void onCCNumberChanged(CharSequence text) {
        ccNumber.setValue(Long.valueOf(text.toString()));
    }

    public void onExpChanged(CharSequence text) {
        exp.setValue(text.toString());
    }

    public void onCCTypeChanged(CharSequence text) {
        ccType.setValue(Integer.valueOf(text.toString()));
    }
}

Part of my layout

<EditText
            android:id="@+id/cvvEdit"
            android:layout_width="wrap_content"
            android:layout_height="48dp"
            android:layout_marginStart="36dp"
            android:layout_marginLeft="36dp"
            android:layout_marginTop="24dp"
            android:afterTextChanged="@{(text) -> creditCardViewModel.onCvvTextChanged(text)}"
            android:ems="10"
            android:inputType="number"
            android:text="@={creditCardViewModel.cvv}"
            app:layout_constraintStart_toEndOf="@+id/cvv"
            app:layout_constraintTop_toBottomOf="@+id/expirationEdit" />

I received the following error when trying to set the cvv in my layout :

      android:text="@={creditCardViewModel.cvv}"

The expression 'creditCardViewModel.getCvv()' cannot be inverted, so it cannot be used in a two-way binding

Details: Two-way binding cannot resolve a setter for java.lang.Integer property 'cvv'

I tried to add getters and setters in the viewModel to get property correctly but still get the error .

Ryan M
  • 18,333
  • 31
  • 67
  • 74
luckysing_noobster
  • 1,933
  • 5
  • 24
  • 50
  • Consider adding setter for your `cvv` livedata. Beware that you not go into infinite loop *(I.e. setting same values again and again)* – Jeel Vankhede Sep 05 '19 at 05:57

1 Answers1

2

Make it your private variable to the public in your ViewModel

public MutableLiveData<String> firstName = new MutableLiveData<>();
public MutableLiveData<String> lastName = new MutableLiveData<>();
public MutableLiveData<Long> ccNumber = new MutableLiveData<>();
public MutableLiveData<Integer> ccType = new MutableLiveData<>();
public MutableLiveData<String> exp = new MutableLiveData<>();
public MutableLiveData<Integer> cvv = new MutableLiveData<>();

And you have to convert your integer to string

android:text="@={String.valueOf(creditCardViewModel.cvv)}"
Akshay Raiyani
  • 1,243
  • 9
  • 21