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.
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))