Android共享视图模型,具有单时间实时数据消耗的实时数据

发布于 2025-01-22 02:51:37 字数 321 浏览 4 评论 0原文

我正在使用共享的视图模型,并在两个片段中共享。这两个片段都在收听一个实时数据,并且还以以下方式处理它,以便

fun getContentIfNotHandled(): StateData<T>? {
    return if (hasBeenHandled) {
        null
    } else {
        hasBeenHandled = true
        return this
    }
}

现在仅消耗一次,因为我观察到一个活数据,其中一个是两个片段,其中一个正在消费实时数据,而另一个正在消耗null。价值。

I am using a shared view model and it is shared across two fragments. Both the fragments are listening for one live data and also handling it in the following way to consume it only once

fun getContentIfNotHandled(): StateData<T>? {
    return if (hasBeenHandled) {
        null
    } else {
        hasBeenHandled = true
        return this
    }
}

Now since I am observing one live data in two fragments, one of them is consuming the live data and the other one is getting a null value.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

冰魂雪魄 2025-01-29 02:51:37

不确定这是否是您的确切用例,但是就我而言,我在订阅Livedata事件的ViewPager中有多个片段。为了确保他们没有冲突,这是我确保我想要的碎片是消耗正确事件的方式。

使用:

class ConditionalEventObserver<T>(
    private val shouldConsumeEvent: (T) -> Boolean,
    private val consumeEvent: (T) -> Unit
) : Observer<Event<T>> {
    override fun onChanged(event: Event<T>) {
        if (!shouldConsumeEvent.invoke(event.peekContent())) return
        event.consumeContentIfAvailable()?.let { value ->
            consumeEvent(value)
        }
    }
}

事件类别:

open class Event<out T>(private val content: T) {
    private var hasBeenHandled = false

    fun consumeContentIfAvailable(): T? =
        if (hasBeenHandled) {
            null
        } else {
            hasBeenHandled = true
            content
        }

    fun peekContent(): T = content
}

假设事件包裹这样的对象,例如

   data class EventPayload(
       val pageIndex: Int,
       //Other attributes
    )

在ViewModel内部:

val sharedEvent = MutableLiveData<Event<EventPayload>>()

在每个片段中的视图中:

viewModel.sharedEvent.observe(viewLifecycleOwner, conditionallyConsumeEvent())

  private fun conditionallyConsumeEvent(): ConditionalEventObserver<ViewModel.SharedEvent> =
        ConditionalEventObserver({ eventPayload ->
            //Add your condition here, you can embed data in the Event Payload
            eventPayload.pageIndex == THIS_FRAGMENT_PAGE_INDEX // In my case, defined in my viewpager callback 
        }) { eventPayload ->
              handleEventInThisFragment(eventPayload)
        }

不完全确定这是否是最佳方法,但这是我这样做的方式。

另一方面,如果您只想在不从片段中消耗片段的情况下读取该值,则仅在事件上峰值内容(PeekContent)可以使用。但是,如果您期望不止一次消费事件并从中触发片段回调,那么您就不应使用事件&amp; EventObserver。

希望有帮助!

Not sure if this is your exact use case, but in my case, I had multiple fragments in a viewpager subscribing to a livedata Event. To ensure their are no conflicts, here is how I ensured that the fragment I wanted was consuming the correct event.

Using:

class ConditionalEventObserver<T>(
    private val shouldConsumeEvent: (T) -> Boolean,
    private val consumeEvent: (T) -> Unit
) : Observer<Event<T>> {
    override fun onChanged(event: Event<T>) {
        if (!shouldConsumeEvent.invoke(event.peekContent())) return
        event.consumeContentIfAvailable()?.let { value ->
            consumeEvent(value)
        }
    }
}

Event class:

open class Event<out T>(private val content: T) {
    private var hasBeenHandled = false

    fun consumeContentIfAvailable(): T? =
        if (hasBeenHandled) {
            null
        } else {
            hasBeenHandled = true
            content
        }

    fun peekContent(): T = content
}

Assuming the event wraps an object like this for example

   data class EventPayload(
       val pageIndex: Int,
       //Other attributes
    )

Inside viewmodel:

val sharedEvent = MutableLiveData<Event<EventPayload>>()

In onViewCreated in each fragment:

viewModel.sharedEvent.observe(viewLifecycleOwner, conditionallyConsumeEvent())

  private fun conditionallyConsumeEvent(): ConditionalEventObserver<ViewModel.SharedEvent> =
        ConditionalEventObserver({ eventPayload ->
            //Add your condition here, you can embed data in the Event Payload
            eventPayload.pageIndex == THIS_FRAGMENT_PAGE_INDEX // In my case, defined in my viewpager callback 
        }) { eventPayload ->
              handleEventInThisFragment(eventPayload)
        }

Not entirely sure if this is the best approach, but it is how I did it.

If on the other hand, you wish to simply read the value without consuming it from your fragments, then just peaking content (peekContent) on the event will work. But if you expect to consume the event more than once and trigger fragment callbacks from that, then you shouldn't be using an Event & EventObserver.

Hope that helps!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文