STATEFLOW/LIVEDATA不更新后,然后按下 我的应用程序中的数据流有问题。 我有两个片段,两个片段都修改了相同的数据,它们都通过集中式存储库类,以便做S ...

问题描述 投票:0回答:3
两个片段管理给定数据的方式是通过存储库类。 该存储库使用kotlin

SharedFlow

与各个片段的视图建模进行通信,然后使用

LiveData

tune the the the the fragment。

这里有一些代码 @AndroidEntryPoint class FragmentA : Fragment() { private val viewModel: ViewModelA by viewModels() override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { val binding = FragmentBinding.inflate(layoutInflater, container, false) viewModel.state.observe(viewLifecycleOwner) { it?.let { binding.fragmentInt.text = it.toString() } } binding.fragmentInt.setOnClickListener { findNavController().navigate( FragmentADirections.actionFragmentAToFragmentB() ) } return binding.root } } @HiltViewModel class ViewModelA @Inject constructor( private val intRepository: IntRepository ) : ViewModel() { private val _state: MutableLiveData<Int?> = MutableLiveData(null) val state: LiveData<Int?> = _state init { viewModelScope.launch { intRepository.observeScreenState().collect { _state.value = it } } intRepository.updateScreenState(1) } } @AndroidEntryPoint class FragmentB : Fragment(R.layout.fragment) { private val viewModel: ViewModelB by viewModels() override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val binding = FragmentBinding.inflate(layoutInflater, container, false) viewModel.state.observe(viewLifecycleOwner) { it?.let { binding.fragmentInt.text = it.toString() } return binding.root } } @HiltViewModel class ViewModelB @Inject constructor( private val intRepository: IntRepository ) : ViewModel() { private val _state: MutableLiveData<Int?> = MutableLiveData(null) val state: LiveData<Int?> = _state init { viewModelScope.launch { intRepository.observeScreenState().collect { _state.value = it } } intRepository.updateScreenState(6) } } class IntRepository @Inject constructor() { private val screenStateFlow = MutableStateFlow<Int?>(null) fun observeScreenState(): Flow<Int?> = screenStateFlow.asStateFlow() fun updateScreenState(value: Int) { screenStateFlow.value = value } }

update:

在广泛的测试和虚拟应用程序的支持之后,我注意到问题似乎是使用Hilt库。  没有它,我的流量完全按照我的期望工作,但是似乎添加DI库正在停止收集本应观察到的数据。  我已经更新了代码,以反映导致我得出这个结论的虚拟应用程序的状态。
没有明确的答案就如何 - 或原因 - 爬行到底这样做。
	

如果您想再次回到其他屏幕并再次回来时,您想再次收听变量。

viewModelScope

您应该在下面的OnViewCreate中指定我在片段中指定的代码网关。
init { viewModelScope.launch { screenStateRepository.observeScreenStateFlow().collect { _state.value = it } } }

碎片;

fun testt() {
viewModelScope.launch {
       screenStateRepository.observeScreenStateFlow().collect {
           _state.value = it
       }
   }
}

您在存储库中的共享流正在使用默认的
android kotlin android-livedata android-navigation kotlin-flow
3个回答
0
投票
参数为0。这意味着,当您的片段脱离屏幕并重新启动时,它们将获得一个新的ViewModel,该模型会创建一个新的状态流,该新状态流正在从存储库中收集到从scrotch中收集的新状态流量共享流,但是共享流不会传递以前发出的任何值。

将您的共享流量更改为具有一个

replay
或将其更改为状态流。
也要查找

replay

shareIn
函数。他们会大量清理您的代码。例如,这可以执行您上面发布的代码所做的事情,同时还可以避免在视图模式不必要的情况下进行不必要的更新。

stateIn



0
投票
// ViewModel A ... private val state = screenStateRepository.observeScreenStateFlow() .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000L), ScreenStateState())

注释,Hilt正在创建我的存储库的替代版本。

由于我是Hilt图书馆的新手,这完全笼罩在我的头上。  但是,经过数小时的调试,并将罪魁祸首缩小到注入的依赖性之后,快速重新阅读了匕首的剑柄文档 - 加上这里有一些有见地的评论的帮助 - 使我能够添加所需的注释的简单答案,例如确保我的存储库的正确行为。
    

由于您的代码非常抽象,我不太了解它。您应该清楚地写出它,因为处理流程中的代码非常复杂,易于误解。我从未使用过共享流,只有状态流。这是我通常所做的事情,您可以参考,希望能帮助您:

Repository

@Singleton

模型A
suspend fun setFrameCustom(frame : String) {
    context.dataStore.edit {
        it[FRAME_CUSTOM_DEFAULT] = frame
    }
}

val frameDefault : Flow<String> = context.dataStore.data.catch {
    exception -> if (exception is IOException) {
        emit(emptyPreferences())
    }
    else {
        emit(emptyPreferences()) throw exception
    }
}.map{preference -> preference[FRAME_CUSTOM_DEFAULT] ?: ""}

companion object {
    val FRAME_CUSTOM_DEFAULT = stringPreferencesKey("FRAME_CUSTOM_DEFAULT")
}

卸下模型
val frameDefaultFlow = repository.frameDefault

0
投票

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.