首页 > 解决方案 > 如何在kotlin中实现双向数据绑定

问题描述

这是我第一次在这里发帖。请原谅我的任何格式问题<3

我正在尝试实现双向数据绑定来记录当前的 BPM 编号。当我单击添加 BPM 或子 BPM 按钮时,我可以在后端观察到视图模型中的 bpm 字段正在更新,但 UI 没有。我的片段、视图模型和布局如下所示。我感谢我收到的所有帮助!

片段布局

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>
        <variable
            name="practiceSegViewModel"
            type="com.example.drumpracticeorganizer.practiceseg.PracticeSegViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/practice_seg_fragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#ececec">

        <EditText
            android:id="@+id/edit_text_bpm"
            style="@style/fragment_add_practice_label"
            android:hint="@string/bpm"
            app:layout_constraintEnd_toEndOf="@+id/edit_text_type"
            app:layout_constraintStart_toStartOf="@+id/edit_text_type"
            app:layout_constraintTop_toBottomOf="@+id/spinner_practice_sub_category" />

        <Button
            android:id="@+id/button_sub_bpm"
            style="@style/fragment_add_practice_button_bpm"
            android:onClick="@{() -> practiceSegViewModel.onDecrementBpm()}"
            android:text="@string/minus_sign"
            app:layout_constraintEnd_toStartOf="@+id/edit_text_bpm_input"
            app:layout_constraintTop_toBottomOf="@+id/edit_text_bpm" />

        <Button
            android:id="@+id/button_add_bpm"
            style="@style/fragment_add_practice_button_bpm"
            android:onClick="@{() -> practiceSegViewModel.onIncrementBpm()}"
            android:text="@string/plus_sign"
            app:layout_constraintStart_toEndOf="@+id/edit_text_bpm_input"
            app:layout_constraintTop_toBottomOf="@+id/edit_text_bpm" />

        <EditText
            android:id="@+id/edit_text_bpm_input"
            style="@style/fragment_add_practice_input"
            android:layout_width="100dp"
            android:gravity="center_horizontal"
            android:inputType="number"
            android:maxLength="3"
            android:text="@={`` + practiceSegViewModel.practice.bpm}"
            android:textAlignment="center"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/edit_text_bpm" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

片段类

class PracticeSegFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        setHasOptionsMenu(true)

        val application = requireNotNull(this.activity).application
        val dataSource = PracticeDatabase.getInstance(application).practiceDatabaseDao
        val viewModelFactory = PracticeSegViewModelFactory(dataSource, application)
        val practiceSegViewModel =
            ViewModelProvider(this, viewModelFactory).get(PracticeSegViewModel::class.java)

        val binding = DataBindingUtil.inflate<FragmentPracticeSegBinding>(
            inflater,
            R.layout.fragment_practice_seg,
            container,
            false
        ).apply {
            this.practiceSegViewModel = practiceSegViewModel
            this.lifecycleOwner = viewLifecycleOwner
        }

        return binding.root
    }
}

查看模型

class PracticeSegViewModel(datasource: PracticeDatabaseDao, application: Application) :
    AndroidViewModel(application) {
 
    private val _practice = MutableLiveData<PracticeEntity>().apply {
        value = PracticeEntity(subCategory = "", category = "", bpm = 0, duration = "0")
    }
    val practice: LiveData<PracticeEntity>
        get() = _practice

    val dao: PracticeDatabaseDao = datasource

    fun onSave() {
        savePractice()
    }

    private fun savePractice() {
        viewModelScope.launch { _practice.value?.let { dao.insert(it) } }
    }

    fun onIncrementBpm() {
        _practice.value?.bpm?.let {
            if (it < 300) {
                _practice.value?.bpm = it.plus(1)
                println(_practice.value?.bpm.toString())
            }
        }
    }

    fun onDecrementBpm() {
        _practice.value?.bpm?.let {
            if (it > 0) {
                _practice.value?.bpm = it.minus(1)
                println(_practice.value?.bpm.toString())
            }
        }
    }
}

标签: androidkotlindata-binding

解决方案


推荐阅读