我有一个片段根据结果发出网络请求,我正在导航到下一个片段。
我无法回到上一个片段,这是问题所在:https://streamable.com/4m2vzg
这是上一个片段中的代码
class EmailInputFragment :
BaseFragment<FragmentEmailInputBinding>(FragmentEmailInputBinding::inflate) {
private val viewModel by viewModels<EmailInputViewModel>()
private lateinit var progressButton: ProgressButton
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
binding.emailToolbar.setNavigationOnClickListener {
val activity = activity as AuthActivity
activity.onSupportNavigateUp()
}
binding.emailNextButton.pbTextview.text = getString(R.string.next)
binding.emailNextButton.root.setOnClickListener {
checkValidEmail()
}
binding.enterEmail.setOnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_DONE) {
checkValidEmail()
}
false
}
binding.enterEmail.doAfterTextChanged {
binding.enterEmailLayout.isErrorEnabled = false
}
viewLifecycleOwner.lifecycleScope.launch {
viewModel.emailCheck.collect {
when (it) {
State.Empty -> {
}
is State.Failed -> {
Timber.e(it.message)
progressButton.buttonFinished("Next")
}
State.Loading -> {
progressButton.buttonActivate("Loading")
}
is State.Success<*> -> {
it.data as EmailCheckModel
when (it.data.registered) {
// New User
0 -> {
findNavController().navigate(
EmailInputFragmentDirections.actionEmailFragmentToSignupFragment(
binding.enterEmail.text.toString().trim()
)
)
}
// Existing User
1 -> {
findNavController().navigate(
EmailInputFragmentDirections.actionEmailFragmentToPasswordInputFragment(
binding.enterEmail.text.toString().trim()
)
)
}
// Unverified user
2 -> {
findNavController().navigate(
EmailInputFragmentDirections.actionEmailFragmentToVerifyUserFragment(
"OK"
)
)
}
}
}
}
}
}
}
private fun checkValidEmail() {
if (!binding.enterEmail.text.toString().trim().isValidEmail()) {
binding.enterEmailLayout.error = "Please enter valid Email ID"
return
}
progressButton = ProgressButton(requireContext(), binding.emailNextButton.root)
viewModel.checkUser(binding.enterEmail.text.toString().trim())
}
}
当我从下一个片段按回时,由于状态仍然是 Success 正在收集流并转到下一个片段,我已经尝试 this.cancel 取消创建时的协程,但仍然无法正常工作。 我该怎么办?
将流收集移动到按钮的onClick会引发无法找到目的地的导航操作的错误
我提出了一个解决方法,即使用
在成功时将流状态重置回 State.EMPTYviewModel.resetState()
在 onSuccess 中,我认为这不是最好的方法,有什么建议吗?
视图模型代码:
private val _emailCheckResponse = MutableStateFlow<State>(State.Empty)
val emailCheck: StateFlow<State> get() = _emailCheckResponse
答案 0 :(得分:1)
如果您的 viewModel.emailCheck
流是热流,那么您需要自行管理其生命周期。如果不是热门的Flow,那么就需要使用LiveData来控制界面,而不是简单的采集Flow。您应该将流转换为 LiveData,并将 Observer 添加到 LiveData 的相应位置。
Cold Flow 中没有与接口生命周期相关的 API,但生命周期已经在 LiveData 中进行了管理。
viewModel.emailCheckLiveData.observe(viewLifecycleOwner, {
when (it) {
State.Empty -> {
}
is State.Failed -> {
Timber.e(it.message)
progressButton.buttonFinished("Next")
}
State.Loading -> {
progressButton.buttonActivate("Loading")
}
is State.Success<*> -> {
it.data as EmailCheckModel
if (it.data.registered) {
val action =
EmailInputFragmentDirections.actionEmailFragmentToPasswordInputFragment(
binding.enterEmail.text.toString().trim()
)
findNavController().navigate(action)
} else {
val action =
EmailInputFragmentDirections.actionEmailFragmentToSignupFragment(
binding.enterEmail.text.toString().trim()
)
findNavController().navigate(action)
}
}
})
您需要定义 emailCheckLiveData。在 Flow.asLiveData()
private val _emailCheckResponse = MutableStateFlow<State>(State.Empty)
val emailCheck: StateFlow<State> get() = _emailCheckResponse
private var mJob: Job? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
lifecycleScope.launchWhenResumed {
if (mJob?.isActive == true) return
mJob = _emailCheckResponse.collectLatest {
when (it) {
State.Empty -> {
}
is State.Failed -> {
Timber.e(it.message)
progressButton.buttonFinished("Next")
}
State.Loading -> {
progressButton.buttonActivate("Loading")
}
is State.Success<*> -> {
it.data as EmailCheckModel
if (it.data.registered) {
val action =
EmailInputFragmentDirections.actionEmailFragmentToPasswordInputFragment(
binding.enterEmail.text.toString().trim()
)
findNavController().navigate(action)
} else {
val action =
EmailInputFragmentDirections.actionEmailFragmentToSignupFragment(
binding.enterEmail.text.toString().trim()
)
findNavController().navigate(action)
}
}
}
}
}
}
override fun onDestroy() {
mJob?.apply {
if (isActive) cancel()
}
super.onDestroy()
}
答案 1 :(得分:-1)
过了一段时间,偶然发现了这篇文章。 https://proandroiddev.com/flow-livedata-what-are-they-best-use-case-lets-build-a-login-system-39315510666d
向下滚动到底部为我的问题提供了解决方案。