2

我已经用视图模型装配了一个简单的登录片段。这是片段:

class LoginFragment : Fragment() {

companion object {
    fun newInstance() = LoginFragment()
}

private lateinit var viewModel: LoginViewModel

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    return inflater.inflate(R.layout.login_fragment, container, false)
}

override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)
    viewModel = ViewModelProviders.of(this).get(LoginViewModel::class.java)

    viewModel.loginState.observe(this, Observer{
        handleState(it)
    })

    login_button.setOnClickListener {
        viewModel.isUserValid(username.text.toString(), pass.toString())
    }
}

private fun handleState(status: RegisterState) {
    if (status.statusMessage.equals("Good"))
        view?.findNavController()?.navigate(R.id.action_registerFragment_to_homeFragment)
    else
        Snackbar.make(login_container, "Welcome to SwA", Snackbar.LENGTH_LONG).show();
}
}

这是我的视图模型:

class LoginViewModel : ViewModel() {

lateinit var auth: FirebaseAuth

private var _loginState = MutableLiveData<LoginState>()
val loginState : MutableLiveData<LoginState> get() = _loginState

init {
    loginState.value = LoginState()
}

fun isUserValid(email: String, password: String): Boolean {
    //Add call to authenticate through firebase
    auth.signInWithEmailAndPassword(email, password)
        .addOnCompleteListener {
            if (it.isSuccessful) {
                // Sign in success, update UI with the signed-in user's information
                val user = auth.currentUser
                //updateUI(user)
            } else {
                // If sign in fails, display a message to the user.
                _loginState.value?.statusMessage = "Authentication Failed"
            }
        }

    return true
}
}

当尝试登录失败时,这会起作用并注册对字符串状态的更改,但是它还会在加载片段时提交 onChange() ,导致在创建片段时它们实际输入任何内容之前,快餐栏出现在 UI 中。如何在不触发 onChange() 的情况下初始化视图状态?

4

1 回答 1

3

LiveData 类有一个方法

 boolean shouldBeActive() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

它检查LifeCycle,ActivityFragment, 的所有者是否处于 STARTED 之后的状态,这意味着 Activity 是否已调用onStart()

因此,每当Activityor观察到 LiveData 时,它都会在调用 onStart之前或之后Fragment获取 LiveData 的值。setValuePostValue

防止同一值多次更新 UI 的方法之一是使用SingleLiveEvent类,例如此处。另一种是使用Event类,示例在这里

于 2019-08-31T06:02:08.243 回答