Search code examples
androidandroid-databindingandroid-livedataandroid-jetpack

How to fix Attempt to invoke virtual method on a null object reference error


im trying to create a login screen with MVVM architecture and got a java.lang.NullPointerException: Attempt to invoke virtual method 'androidx.lifecycle.MutableLiveData com.log.ui.login.LoginViewModel.getUser()' on a null object reference

Please help to pinpoint the cause of this error. I think issue is something to do with Viewmodel. Any suggestion regarding this would be highly appreciated.

My Login Fragment code

public class LoginScreen extends Fragment {


    private LoginViewModel loginViewModel;

   private FragmentLoginBinding binding;

   public View onCreateView(LayoutInflater inflater,
                            @Nullable ViewGroup container,
                            @Nullable Bundle savedInstanceState){

     //  binding=FragmentLoginBinding.inflate(getLayoutInflater(),container,false);
    binding= DataBindingUtil.inflate(inflater,R.layout.fragment_login,container,false);
       View view = binding.getRoot();


       binding.setLifecycleOwner(this);
       binding.setLoginViewModel(loginViewModel);
       //here data must be an instance of the class MarsDataProvider




 loginViewModel.getUser().observe(this,new Observer<Repository>(){

     public void onChanged(Repository loginUser) {

         if (TextUtils.isEmpty(Objects.requireNonNull(loginUser).getStrEmailAddress())) {
             binding.txtEmailAddress.setError("Enter an E-Mail Address");
             binding.txtEmailAddress.requestFocus();
         }
         else if (!loginUser.isEmailValid()) {
             binding.txtEmailAddress.setError("Enter a Valid E-mail Address");
             binding.txtEmailAddress.requestFocus();
         }
         else if (TextUtils.isEmpty(Objects.requireNonNull(loginUser).getStrPassword())) {
             binding.txtPassword.setError("Enter a Password");
             binding.txtPassword.requestFocus();
         }
         else if (!loginUser.isPasswordLengthGreaterThan5()) {
             binding.txtPassword.setError("Enter at least 6 Digit password");
             binding.txtPassword.requestFocus();
         }
         else {
             binding.lblEmailAnswer.setText(loginUser.getStrEmailAddress());
             binding.lblPasswordAnswer.setText(loginUser.getStrPassword());
         }

     }

       });

      // return binding.getRoot();
       return view;
   }
}

LoginViewModel.Java

public class LoginViewModel extends ViewModel {

    public MutableLiveData<String> EmailAddress = new MutableLiveData<>();
    public MutableLiveData<String> Password = new MutableLiveData<>();

    private MutableLiveData<Repository> userMutableLiveData;

    public MutableLiveData<Repository> getUser() {

        if (userMutableLiveData == null) {
            userMutableLiveData = new MutableLiveData<>();
        }
        return userMutableLiveData;

    }

    public void onClick(View view) {

        Repository loginUser = new Repository(EmailAddress.getValue(), Password.getValue());

        userMutableLiveData.setValue(loginUser);

    }

}

My Modelclass can be found here.

public class Repository {

    private String strEmailAddress;
    private String strPassword;

    public Repository(String EmailAddress, String Password) {
        strEmailAddress = EmailAddress;
        strPassword = Password;
    }

    public String getStrEmailAddress() {
        return strEmailAddress;
    }

    public String getStrPassword() {
        return strPassword;
    }

    public boolean isEmailValid() {
        return Patterns.EMAIL_ADDRESS.matcher(getStrEmailAddress()).matches();
    }


    public boolean isPasswordLengthGreaterThan5() {
        return getStrPassword().length() > 5;
    }

}

Solution

  • From what I see, you have not initialized your viewmodel. Put the below line before setLoginViewModel

    LoginViewModel loginViewModel = ViewModelProviders.of(getActivity()).get(LoginViewModel.class)