android - 当viewmodel持有来自客户端的价值时,如何阻止观察者被多次触发?
问题描述
免责声明,这与我之前的问题不同
我是 MVVM 的新手,我有点困惑。
所以如果用户单击我的片段中的按钮,那么我将向服务器发出请求以检查该用户是否创建了音乐事件,如果他没有创建音乐事件然后移动到片段 B。这是我的片段 A
class FragmentA : Fragment() {
lateinit var model: AViewModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
model = ViewModelProvider(this).get(AViewModel::class.java)
button.setOnClickListener {
model.checkIfUserHasCreatedEvent()
}
model.hasCreatedEvent.observe(this, Observer { hasCreatedEvent ->
if (!hasCreatedEvent) {
val chooseEventNameDestination = CreateEventFragmentDirections.actionToCreateEventName()
findNavController().navigate(chooseEventNameDestination)
model.navigationHasBeendHandled()
}
})
}
}
这是这个片段的视图模型
class AViewModel(application: Application) : AndroidViewModel(application) {
val _hasCreatedEvent : MutableLiveData<Boolean> = UserClient.hasCreatedEvent
val hasCreatedEvent : LiveData<Boolean>
get() = _hasCreatedEvent
fun checkIfUserHasCreatedEvent() {
UserClient.checkIfUserHasCreatedAnEvent()
}
fun navigationHasBeendHandled() {
_hasCreatedEvent.value = true // to reset data, to avoid the value to be false
}
}
这是 UserClient(为简单起见,我跳过了存储库)
object UserClient {
val hasCreatedEvent = MutableLiveData<Boolean>()
fun checkIfUserHasCreatedAnEvent() {
// perform networking to server ....
// and post the value after getting the response
hasCreatedEvent.postValue(result)
}
}
当我第一次单击该按钮时,它按预期工作,它从片段 A 移动到片段 B。因为在检查到服务器后,hasCreatedEvent == false
.
当我从片段 B 回到片段 A 时,就会出现问题。
当从fragment B返回时,fragment A中的observer被多次触发,即使我没有点击按钮,它也会自动触发。
model.hasCreatedEvent.observe(this, Observer { hasCreatedEvent ->
// triggered 3 times in here
Log.d("AViewModel","result: $hasCreatedEvent")
// result: true
// result: false <--- the problem
// result: true
if (!hasCreatedEvent) {
// because there is a false value ...
// then this block is triggered, and it makes it moves to fragmentB again
}
})
我相信true
价值来自navigationHasBeendHandled
我的 viewModel 的方法,但我不明白为什么false
当我从片段 B 回到片段 A 时再次有价值?即使我没有点击按钮
我假设false
价值来自于UserClient.hasCreatedEvent
从服务器发出请求后持有的价值。
但我不知道如何解决这个问题,因为该false
值使其再次自动移动到片段 B。
java或者kotlin都可以
解决方案
因为当你回到 FragmentA 时,viewModel 又被创建了,并且对于 java/kotlin 的 Boolean 初始值为 false。一个简单的解决方案是为你的 Activity 创建 ViewModel 而不是 Fragments,这是 Google 推荐的,让 viewModel 遵循 Activity 的 LifeCycle,并且这个 Activity 中的所有 Fragment 都会共享这个 ViewModel。