mvvmandroid-livedataviewmodelfactory

LiveData doesn't update value


I try to put value to liveFata from viewModelScope, but when I check that value within fragment it's null. I think, there is problem with instance of viewModel, but I can't find solution. Please, any advice?

class LoginViewModel(private val loginDao: LoginDao) : ViewModel() {

    private val _checkingValue = MutableLiveData<Boolean>()
    val checkingValue: LiveData<Boolean> = _checkingValue

    /* Validation login data */
    fun checkUserFirstNameAndPassword(firstName: String, password: String): Int {
        return if (firstName.isEmpty()) Const.FIRST_NAME_IS_EMPTY
        else {
            if (password.isEmpty()) {
                Const.PASSWORD_IS_EMPTY
            } else {
                Const.VALID_DATA
            }

        }
    }

    fun checkingIsUserAccountExist (firstName: String) {
        viewModelScope.launch {
            try {
                _checkingValue.value = loginDao.isUserAccountExist(firstName)
            }catch (e: Exception) {
                Log.d("LoginViewModel", "Hello from background thread! Something wrong, try Later!")
            }
        }
    }
}


class LoginViewModelFactory(
    private val loginDao: LoginDao
) : ViewModelProvider.Factory {
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(LoginViewModel::class.java)) {
            @Suppress("UNCHECKED_CAST")
            return LoginViewModel(loginDao) as T
        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }
}
class LoginFragment : Fragment() {
    private lateinit var binding: FragmentLoginBinding
    private val viewModelFactory by lazy {
        LoginViewModelFactory((activity?.application as SignInApplication).database.getDao())
    }
    private val viewModel: LoginViewModel by lazy {
        ViewModelProvider(this, viewModelFactory)[LoginViewModel::class.java]
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        val binding = FragmentLoginBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val btLogin: TextView = view.findViewById(R.id.bt_log_in)
        var firstName: EditText = view.findViewById(R.id.enter_first_name)
        var password: EditText = view.findViewById(R.id.password_edit)


        btLogin.setOnClickListener {

            val firstName = firstName.text.toString().lowercase()
                .replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() }
                .filter { !it.isWhitespace() }
            val password = password.text.toString().lowercase()
                .replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() }
                .filter { !it.isWhitespace() }

            val loginDataState = viewModel.checkUserFirstNameAndPassword(
                firstName,
                password
            )
            Log.d("LoginFragment", "$loginDataState")
            Log.d("LoginFragment", firstName)
            Log.d("LoginFragment", password)

            if (loginDataState == Const.FIRST_NAME_IS_EMPTY) {
                alertDialog("Enter your first name!")
            } else if (loginDataState == Const.PASSWORD_IS_EMPTY) {
                alertDialog("Enter your password")
            } else {
                viewModel.checkingIsUserAccountExist(firstName)
                /* If user account exist in Db isUserAccountExist = true */
                val isUserExist = viewModel.checkingValue.value
                Log.d("LoginFragment", "isUserAccountExist $isUserExist")

                if (isUserExist == true) {
                    val action = LoginFragmentDirections.actionLoginFragmentToRootFragment()
                    findNavController().navigate(action)
                } else {
                    alertDialog("User isn't exist, please sign up!")
                    val action = LoginFragmentDirections.actionLoginFragmentToSignInPageFragment()
                    findNavController().navigate(action)
                    Log.d("LoginFragment", "isUserAccountExist 2 option $isUserExist")
                }
            }
        }
    }

    /* Launch alert dialog  */
    private fun alertDialog(state: String) {
        AlertDialog.Builder(requireContext())
            .setMessage(state)
            .setPositiveButton("Ok", null)
            .create()
            .show()
    }
}

I tried didn't use viewModelfactory, but same result. It looks like I get different instance of ViewModel and LiveData.


Solution

  • I find solution. I can use Observer not only for UI. After getting liveData value via an Observer, I started navigate fun within observer. Thank everybody, who support me))