繁体   English   中英

从存储库发送数据以查看 MVVM 架构中的 model

[英]Send data from repository to view model in MVVM architecture

我对使用 MVVM 架构感到困惑,在一些教程中, LiveData存储在存储库中,然后传递给ViewModel 在许多其他情况下, LiveData中定义,并使用 function 的结果传递给ViewModel 谷歌说

在数据层 class 中使用 LiveData 对象可能很诱人,但 LiveData 并非旨在处理异步数据流。 ........ 如果您需要在应用程序的其他层中使用数据流,请考虑使用 Kotlin 流,然后使用 asLiveData() 在 ViewModel 中将它们转换为 LiveData。 .... 对于使用 Java 构建的代码库,请考虑将 Executors 与回调或 RxJava 结合使用。

我更喜欢使用 Kotlin coroutinesFlows 但我不知道在我的情况下是否真的需要。 我正在开发一个聊天应用程序。 当接收到消息时,将在存储库中调用侦听器并在其中接收消息数据。 (监听器在后台线程中运行)现在我想将消息 object 发送到ViewModel并将其添加到存储消息列表的LiveData中。

object ChatsRepo {

fun listen(socket: Socket) {
    socket.on(Config.ON_MESSAGE, onMessage)
}

fun sendMessage(socket: Socket, json: String) {
    socket.emit(Config.ON_MESSAGE, json)
}

private val onMessage = Emitter.Listener { args: Array<Any> ->
    //This message object must be sent to ViewModel
    val message = Gson().fromJson(args[0].toString(), Message::class.java)
}
}

我可以使用高阶 function 轻松做到这一点:

object ChatsRepo {

lateinit var listener: (Message) -> Unit

private val onMessage = Emitter.Listener { args: Array<Any> ->
    val message = Gson().fromJson(args[0].toString(), Message::class.java)
    listener(message)
}
}

但是使用 Kotlin coroutines还是Flows更好? 在一些类似的情况下,需要向ViewModel发送一个列表。

我可以使用高阶 function 轻松做到这一点。

是的,这是一个回调,您可以使用它来通知ViewModel新消息。 Kotlin 协程有助于避免回调并具有顺序代码。

在您的情况下, onMessage是数据的热Flow ,我们可以使用SharedFlow将其转换为热流:

private val _messagesFlow = MutableSharedFlow<Message>(extraBufferCapacity = 64)
val messagesFlow: SharedFlow<Message> = _messagesFlow

private val onMessage = Emitter.Listener { args: Array<Any> ->
    val message = Gson().fromJson(args[0].toString(), Message::class.java)
    messagesFlow.tryEmit(message)
}

ViewModel中,如果需要,很容易使用asLiveData LiveData

ChatsRepo.messagesFlow.asLiveData()

使用asLiveData()扩展 function 的依赖项:

def lifecycle_version = "2.4.0"

implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"

如果你是 Rxjava 高手,我不会推荐你使用 flow/livedata。 我认为 flow/livedata 是为 UI Reactive 而设计的,而不是为底层数据转换而设计的。 所以你可以在数据仓库中使用 rxjava,在 viewmodel 中,你可以将它转换为 livedata 并使用它。

Livedata 从来都不是为反应流设计的,它总是用于last layer (viewmodel to view) ,当 livedata 与改造(使用 calladapter)和房间(谷歌做到了)一起使用时,有/有解决方法。
而现在由于协程的兴起推荐的方式是使用kotlin Flows来处理业务逻辑但是需要注意的事情:
1- regular flow不是可观察的,但 livedata 是可观察的。
2-使用regular flows管理 UI state 并不好,但您可以使用livedata来做到这一点。
3- livedata 是lifecycle aware的,但流不是。
4- livedata不是反应性的,但flows是。
5- livedata为您提供它接收到的唯一最新值,但regular flows从存储桶中一一抛出值

您可能已经注意到,我说很多regular flows不是flow ,因为还有其他与流程相关的机制,您可以管理 UI state,它们是stateFlowsharedFlow
Stateflow 是livedata的替代品,缺点是您必须编写更多代码以使其具有生命周期意识,因为它不是预构建的,并且 stateflow 始终为您提供在配置更改或屏幕切换(片段导航)期间持续存在的最后一个值。
sharedFlows非常适合管理一次性事件,例如 toastMsgs、snackbar 等。 sharedFlow实际上是BroadcastChannels的替代品。

暂无
暂无

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

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