简体   繁体   English

为什么每个活动都更新到原始实时数据而不是最近的实时数据?

[英]Why each activity is getting update to the original live data instead of recent live data?

MeetingViewModel会议视图模型

fun observeAttendeesJoined(): LiveData<Array<AttendeeInfo>>? {
        return Repository.getAttendeesJoined()
    }

There is a singleton repository using kotlin's object declaration.有一个使用 kotlin 的 object 声明的 singleton 存储库。 Repository has a live data which is being observed by BaseActivity.存储库有一个 BaseActivity 正在观察的实时数据。

Repository存储库

 fun getAttendeesJoined(): LiveData<Array<AttendeeInfo>>? {
        if (attendeesJoined == null) {
            attendeesJoined = MutableLiveData()
        }
        return attendeesJoined
    }

BaseActivity基本活动

private fun observeAttendeesJoined() {
        meetingViewModel.observeAttendeesJoined()?.observe(this) {
            Timber.d(" :$LOG_APP_NAME: BaseActivity: :setObservers: onAttendeesJoined: $it")
            lifecycleScope.launchWhenResumed {
                onAttendeesJoined(it)
            }
        }
    }

A foreground service changes the value of the corresponding mutable live data.前台服务会更改相应可变实时数据的值。 BaseActivity receives the update and we are showing the snackbar. BaseActivity 收到更新,我们正在显示小吃栏。 Now, when we are changing the activity, the same result is being triggered again even when it is not triggering by the foreground service.现在,当我们更改活动时,即使它不是由前台服务触发,也会再次触发相同的结果。

For example, if we are in activity A (that extends the BaseActivity) and the foreground service changes the value of a total numbers of new attendees to 5, we are showing it in the activity A as 5 users have joined the meeting .例如,如果我们在activity A (that extends the BaseActivity)中,前台服务将新参加者总数的值更改为 5,我们在activity A中显示它,因为有 5 个用户加入了会议 User spends some time on the activity A .用户在activity A上花费了一些时间。 After some time, when the user moves to activity B (that is also extending BaseActivity) , without any response from foreground service, the activity B receives the same last update that was received by activity A and hence, activity B also shows the snackbar that 5 users have joined the meeting and this pattern continues for all the activities.一段时间后,当用户移动到activity B (that is also extending BaseActivity)时,没有来自前台服务的任何响应, activity B接收到与活动 A 接收到的相同的最后更新,因此,活动 B 还显示了小吃栏5 位用户加入了会议,并且所有活动都继续采用这种模式。

MeetingViewModel会议视图模型

fun onAttendeesJoined(attendeeInfo: Array<AttendeeInfo>) {
        Timber.d(" :$LOG_APP_NAME: MeetingViewModel: :onAttendeesJoined: :size: ${attendeeInfo.size}")
        attendeeInfo.forEach {
            Timber.d(" :$LOG_APP_NAME: MeetingViewModel: :onAttendeesJoined: $attendeeInfo")
        }
        Repository.setAttendeesJoined(attendeeInfo)
    }

Service服务

 override fun onAttendeesJoined(attendeeInfo: Array<AttendeeInfo>) {
        attendeeInfo.forEach {
            Timber.d(" :$LOG_APP_NAME: ChimeService: :onAttendeesJoined: :id: ${it.attendeeId} :externalId: ${it.externalUserId} :attendeeInfo: $it :responseSize: ${attendeeInfo.size}")
        }
        meetingViewModel.onAttendeesJoined(attendeeInfo)
    }

Whenever the foreground service changes the corresponding mutable live data, new activity (activity B in our example) should get the update only if new data (5) gets changed because meetingViewModel.observeAttendeesJoined() returns new data only.每当前台服务更改相应的可变实时数据时,新活动(在我们的示例中为活动 B)只有在新数据 (5) 发生更改时才应获得更新,因为meetingViewModel.observeAttendeesJoined()仅返回新数据。

How to receive the unique update across the activities?如何在活动中接收独特的更新?

Instance of MeetingViewModel is different for each activity but repository data is a singleton (object declaration of kotlin), isn't it?每个活动的MeetingViewModel实例都不同,但存储库数据是 singleton(kotlin 的对象声明),不是吗?

I tried to understand Transformations.map and switchMap but could not get any idea how to use it to solve the issue.我试图理解Transformations.mapswitchMap但不知道如何使用它来解决问题。

Thank you in anticipation.谢谢你的期待。

This is how LiveData is designed to work.这就是 LiveData 的工作原理。 It's for getting the latest state of data, and not intended to be a message broadcaster.它用于获取最新的 state 数据,而不是作为消息广播者。 There are various hacks out there to try to make LiveData work for this purpose.有各种黑客可以尝试使 LiveData 用于此目的。 You can do a web search for SingleLiveEvent to find various articles on the topic.您可以通过 web 搜索 SingleLiveEvent 以查找有关该主题的各种文章。

You might consider using Kotlin's MutableSharedFlow for doing this instead of LiveData.您可以考虑使用 Kotlin 的 MutableSharedFlow 来代替 LiveData。 It has a replay parameter that you can set to 0 (which is the default) so your new Activities won't receive updates that have already occurred.它有一个replay参数,您可以将其设置为 0(这是默认值),这样您的新活动将不会收到已经发生的更新。 In my opinion, this is a much cleaner solution that SingleLiveEvent.在我看来,这是一个比 SingleLiveEvent 更干净的解决方案。

Your repo can expose the property:您的 repo 可以公开该属性:

val attendeesJoined = MutableSharedFlow<Array<AttendeeInfo>>()

and your ViewModel can pass it through:并且您的 ViewModel 可以通过它:

val attendeesJoined: SharedFlow<Array<AttendeeInfo>> = Repository.getAttendeesJoined()

You can post values to the MutableSharedFlow with tryEmit() .您可以使用tryEmit()将值发布到 MutableSharedFlow。

Your Activities can collect (observe) the Flow on their lifecycleScope s, which will result in analagous behavior to observing a LiveData, because the lifeCycleScope will automatically cancel collection when the Activity is closed.您的活动可以在其lifecycleScope范围内收集(观察)流,这将导致类似于观察lifeCycleScope的行为,因为当活动关闭时生命周期范围将自动取消收集。

private fun observeAttendeesJoined() {
    lifecycleScope.launchWhenResumed {
        meetingViewModel.attendeesJoined.collect {
            Timber.d(" :$LOG_APP_NAME: BaseActivity: :setObservers: onAttendeesJoined: $it")
            onAttendeesJoined(it)
        }
    }
}

Also, a suggestion.另外,提个建议。 Arrays should rarely be used. Arrays 应该很少使用。 It is cleaner/safer for a repository to expose read-only Lists.存储库公开只读列表更清洁/更安全。 Arrays are mutable and fixed size, so they have a narrow set of uses, and are generally for low-level work. Arrays 是可变大小和固定大小的,因此它们的用途很窄,通常用于低级工作。

MutableLiveData stores last value and emits it when you observe it in another Activity (because you store MutableLiveData in singleton). MutableLiveData存储最后一个值并在您在另一个Activity中观察它时发出它(因为您将MutableLiveData存储在单例中)。 Maybe you want something like SingleLiveEvent .也许您想要SingleLiveEvent类的东西。 See https://medium.com/@abhiappmobiledeveloper/android-singleliveevent-of-livedata-for-ui-event-35d0c58512da请参阅https://medium.com/@abhiappmobiledeveloper/android-singleliveevent-of-livedata-for-ui-event-35d0c58512da

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM