我已在我的应用程序中从使用 LiveData 切换到 StateFlow,并将其应用到数据绑定中。但是更改 StateFlow 的值后,UI 没有更新。根据我从StateFlow 文档中了解到的情况,我只需为value
StateFlow 的属性分配一个新值即可更新其消费者。
下面,我有一个时间字段,我使用MaterialTimePicker
对话框更新值。selectedAlarm
但是在我更改时间并为我的视图模型的属性 ( )分配一个新值后StateFlow
,UI 不会针对新值进行更新。我不确定我的错误在哪里或缺少什么。
下面是我的AlarmFormFragment
:
@AndroidEntryPoint
class AlarmFormFragment : Fragment() {
private val alarmsViewModel: AlarmsViewModel by activityViewModels()
private var _binding: FragmentAlarmFormBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentAlarmFormBinding.inflate(inflater, container, false)
binding.alarmsViewModel = alarmsViewModel
binding.lifecycleOwner = viewLifecycleOwner
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
setUpTimeField()
}
private fun setUpTimeField() {
alarmsViewModel.selectedAlarm.value.let { alarm ->
binding.llTimeField.setOnClickListener {
// Create and then show time picker
val picker =
MaterialTimePicker.Builder()
.setTimeFormat(TimeFormat.CLOCK_12H)
.setTitleText("Set Time")
.setHour(alarm.time.get(Calendar.HOUR_OF_DAY))
.setMinute(alarm.time.get(Calendar.MINUTE))
.build()
picker.addOnPositiveButtonClickListener {
alarm.time.set(Calendar.HOUR_OF_DAY, picker.hour)
alarm.time.set(Calendar.MINUTE, picker.minute)
alarmsViewModel.selectedAlarm.value = alarm
}
picker.show(childFragmentManager, "TIME_INPUT_DIALOG")
}
}
}
}
下面是 xml 文件AlarmFormFragment
:
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
<import type="com.example.myclock.utilities.Utility" />
<import type="com.example.myclock.utilities.SnoozeUtils"/>
<variable
name="alarmsViewModel"
type="com.example.myclock.viewmodels.AlarmsViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".fragments.AlarmFormFragment">
<!-- Form Fields -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<!-- Time Field -->
<LinearLayout
android:id="@+id/llTimeField"
style="@style/FormFieldLayoutStyle">
<TextView
style="@style/FormFieldTextStyle.Label"
android:text="@string/label_time" />
<TextView
android:id="@+id/tvTime"
style="@style/FormFieldTextStyle.Value"
android:text="@{Utility.INSTANCE.timeToString(alarmsViewModel.selectedAlarm.value.time)}" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
下面是我的AlarmsViewModel
:
@HiltViewModel
class AlarmsViewModel @Inject constructor(
private val alarmsRepository: AlarmsRepository
) : ViewModel() {
private val _alarms = MutableStateFlow<List<Alarm>>(emptyList())
val alarms: StateFlow<List<Alarm>> get() = _alarms
var selectedAlarm = MutableStateFlow(Alarm())
...
}
以下是数据类Alarm
:
@Parcelize
@Entity
class Alarm(
@PrimaryKey(autoGenerate = true) val id: Int = 0,
var time: Calendar = Calendar.getInstance(),
...
) : Parcelable {
...
}