首页 > 解决方案 > 当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都可以

标签: androidkotlinandroid-livedataandroid-architecture-componentsandroid-jetpack

解决方案


因为当你回到 FragmentA 时,viewModel 又被创建了,并且对于 java/kotlin 的 Boolean 初始值为 false。一个简单的解决方案是为你的 Activity 创建 ViewModel 而不是 Fragments,这是 Google 推荐的,让 viewModel 遵循 Activity 的 LifeCycle,并且这个 Activity 中的所有 Fragment 都会共享这个 ViewModel。


推荐阅读