[英]Unable to switch to MainActivity after data insertion from repository in MVVM architecture
[英]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 coroutines
或Flows
。 但我不知道在我的情况下是否真的需要。 我正在开发一个聊天应用程序。 当接收到消息时,将在存储库中调用侦听器并在其中接收消息数据。 (监听器在后台线程中运行)现在我想将消息 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,它们是stateFlow
和sharedFlow
。
Stateflow 是livedata
的替代品,缺点是您必须编写更多代码以使其具有生命周期意识,因为它不是预构建的,并且 stateflow 始终为您提供在配置更改或屏幕切换(片段导航)期间持续存在的最后一个值。
sharedFlows
非常适合管理一次性事件,例如 toastMsgs、snackbar 等。 sharedFlow
实际上是BroadcastChannels
的替代品。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.