android - 可变实时数据值在创建 fragment 时更新

标签 android android-fragments android-livedata mutablelivedata

我已经用 View 模型装配了一个简单的登录 fragment 。 这是 fragment :

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();
}
}

这是我的 View 模型:

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
}
}

当尝试登录失败时,它会工作并注册对字符串状态的更改,但是它还会在加载 fragment 时提交 onChange() ,导致在 fragment 实际输入任何内容之前, snackbar 就出现在 UI 中被 build 。如何在不触发 onChange() 的情况下初始化 View 状态?

最佳答案

LiveData 类有一个方法

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

它检查 LifeCycleActivityFragment 的所有者是否处于 STARTED 后的状态,这意味着对于 Activity 来说,如果它具有调用了onStart()

因此,每当 ActivityFragment 观察 LiveData 时,它都会在 onStart 之后通过 setValuePostValue 获取 LiveData 的值被调用。

防止相同值多次更新 UI 的方法之一是使用 SingleLiveEvent 类,例如 here 。另一种是使用 Event类,例如here .

关于android - 可变实时数据值在创建 fragment 时更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57734738/

相关文章:

android - 使用 "clear all"禁用关闭通知,但仍然可以滑动?

android - 应用于嵌套 fragment 的 fragment 间通信?

android - 无法在 Activity 和 Fragment : 之间共享 Viewmodel

android - 修改从 Room 获取的 LiveData 项目

java - 切换此标记后预期的标签

android - CalledFromWrongThreadException

android - 无法解析 : com. android.databinding :library:3. 1.2

java - Android studio中的CardView、Recyclerview Fragment中点击不同的卡片即可打开不同的Activity

java - Android studio Google Map API 与 fragment

android - LiveData setValue 在 doOnComplete android RXJava 之后不起作用