使用流在服务和片段之间"talk"



2年多了,我在"更新"。我自己与android/kotlin的变化,天哪,它改变了很多。

场景

  • 我有MyFragmentMyFragmentViewModel的主要活动
  • 我有一个前台服务MyService
  • 我有一个存储库,它有一个Flow<MyState>,应该由MyFragmentViewModel和myservice收集基本上在过去,当我想要在未导出的服务和主要活动之间进行通信时,我使用LocalBroadCastReceiver,它工作得非常好,并且消除了两者之间的紧密耦合。现在这已经被弃用了,所以我想为什么不在存储库中有一个流,每当它发生变化时就会被收集,这样任何客户端都可以对变化做出反应。

为了简单起见,这里是一些与

相关的基本代码
enum class MyState{
STATE_LOADING,
STATE_NORMAL,
....
}
class MyRepository(){
//for simplicity there is no private immutable _state for now
val state:MutableStateFlow<MyState> = MutableStateFlow(MyState.STATE_NORMAL)

fun updateState(newState: MyState){
state.value = newState
}
}
class MyFragmentViewModel @Inject constructor(
private val myRepository: MyRepository
): ViewModel(){
fun updateCurrentState(){
myRepository.updateState(MyState.STATE_LOADING)
}
}
@AndroidEntryPoint
class MyService:Service(){
@Inject lateinitvar myRepository: MyRepository
private val myJob = SupervisorJob()

private val myServiceScope = CoroutineScope(Dispachers.IO+myJob)
fun listenForState(){
myServiceScope.launch{
myRepository.state.collect{
when(it)
....
}
}
}
}

发生的事情是,在启动时,MyService中的collect确实获得初始值STATE_NORMAL,但当我从MyFragmentViewModel更新MyRepository状态时,该值未被服务接收。

我的问题:

  • 我做错了什么?是否与服务范围/协同程序以及collect的工作方式有关?
  • 从架构上讲,这是一个好方法吗?还是有更好的方法?

你的服务永远不应该与存储库通信,因为它应该在UI模块下,因此它必须与ViewModel通信,后者进一步与存储库通信。

你可以在这里阅读我对MVVM模式的回答:

这是正确的Android MVVM设计吗?

。我已经在这里解释了MVVM模式。

对于您的特定用例,我建议您检查这个github - project:

https://github.com/mitchtabian/Bound-Services-with-MVVM

在ReadMe部分有一个Youtube视频的链接,该视频将深入解释如何使用MVVM服务。


同样在你的代码中,你已经使用了枚举类,这是没有错的,但是因为你正在使用,你可以使用密封类,它是建立在enum之上的,并提供了维护严格的层次结构。你的密封类形式的枚举类将以以下方式呈现:

sealed class MyState{
object State_Loading : MyState()
object State_Normal : MyState()
}

对于您无法更新数据的问题,我建议您尝试

fun updateState(newState: MyState){
state.emit( newState)
}

如果这不起作用,您需要使用Log从数据经过的每一步进行调试,并知道错误发生在哪里

相关内容

  • 没有找到相关文章

最新更新