我尝试从 viewModelScope 为 liveFata 赋值,但是当我在片段中检查该值时,它为空。我想,viewModel 的实例有问题,但我找不到解决方案。请问有什么建议吗?
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()
}
}
我试过没有使用 viewModelfactory,但结果相同。看起来我得到了不同的 ViewModel 和 LiveData 实例。
我找到了解决方案。我不仅可以将 Observer 用于 UI。通过 Observer 获取 liveData 值后,我开始在观察者中导航乐趣。谢谢大家支持我))