android 如何在不发出到收集器的情况下更新StateFlow?

kqqjbcuj  于 2023-06-04  发布在  Android
关注(0)|答案(1)|浏览(620)

关于UI layer和单向数据流(UDF)的问题。我们有DetailFragmentEditText

  • 当用户打开现有详细信息时,文本从StateFlow<DetailUiState>开始由ViewModel填充。
  • 现在用户更改文本,DetailFragment发送新文本到ViewModel,更新UI状态,并由于collect片段接收更新的状态。因此,片段调用setText,触发再次向ViewModel发送相同的文本。
  • 如果我们在接收新文本时没有更新UI状态,对于任何配置更改(屏幕旋转),片段在重新创建时接收旧文本值。

如何走出这样的怪圈?

data class DetailUiState(
    val text: String
)

class DetailViewModel {

   private val _uiState = MutableStateFlow(DetailUiState("first text"))
   val uiState = _uiState.asStateFlow()

   fun onTextChanged(newValue: String) {
       _uiState.value = DetailUiState(newValue)
   }
}

class DetailFragment {

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        repeatOnStartedLatest(viewModel.uiState) { // flow.collect shortcut
            binding.editText.setText(it.text)
        }
       
        binding.editText.doAfterTextChanged {
            viewModel.onTextChanged(binding.editText.getTextAsString())
        }
    }

}
58wvjzkj

58wvjzkj1#

处理这个问题的一个更好的方法是使用双向数据绑定特性。
在ViewModel类中有一个字段,例如:

val text = MutableStateFlow("First value")

在片段的布局文件中:

<data class=".FragmentBinding">
        <variable
            name="vm"
            type="com.sample.YourViewModel" />
    </data>

    <EditText
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:inputType="text"
        android:text="@={vm.text}" <!-- 2-way text binding -->
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

现在,从Fragment类传递ViewModel引用和生命周期所有者:

private val vm: YourViewModel by viewModels()

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
    binding = FragmentBinding.inflate(inflater, container, false)
    binding.vm = vm
    binding.lifecycleOwner = viewLifecycleOwner
    return binding.root
}

相关问题