Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/203.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 使用LiveData的SeekBar和EditText的进展_Android_Kotlin_Mvvm_Viewmodel_Android Livedata - Fatal编程技术网

Android 使用LiveData的SeekBar和EditText的进展

Android 使用LiveData的SeekBar和EditText的进展,android,kotlin,mvvm,viewmodel,android-livedata,Android,Kotlin,Mvvm,Viewmodel,Android Livedata,我有文本输入和SeekBar 我需要通过文本输入值(数字)来更改导引头的值,并通过导引头更改值来更改文本值。使用视图模型和实时数据绑定 所以,我在viewmodel类中有两个中介实时数据 视图模型: val progress: MediatorLiveData<Int> by lazy { MediatorLiveData<Int>() } val progressText: MediatorLiveData<String> by lazy { Mediato

我有文本输入和SeekBar

我需要通过文本输入值(数字)来更改导引头的值,并通过导引头更改值来更改文本值。使用视图模型和实时数据绑定

所以,我在viewmodel类中有两个中介实时数据

视图模型:

val progress: MediatorLiveData<Int> by lazy { MediatorLiveData<Int>() }
val progressText: MediatorLiveData<String> by lazy { MediatorLiveData<String>() }
xml和数据绑定如下所示:

<AppCompatSeekBar android:id="@+id/seekbar"
            style="@style/SeekerItemStyle"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:progress="@={viewModel.progress}" />

 <EditText android:id="@+id/input_progress"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@={viewModel.progressText}" />

(考虑输入文本)

但是,这里我得到了无限循环,因为一个调停者的变化影响到另一个调停者,而另一个调停者的变化又回到了一个调停者


这里有解决这一逻辑的最佳实践和更聪明的解决方案吗?谢谢。

您可以分别为搜索者和文本制作两对MediatorLiveData LiveData。例如,第一个MediatorLiveData观察搜索栏的更改,当应用更改时,它会更改EditText的LiveData,反之亦然:您有MediatorLiveData,它会在每次EditText中的内容更改时更改SeekBar的LiveData。

您可以使用

创建一个新的LiveData对象,该对象在源LiveData值更改之前不会发出值。如果equals()生成false,则认为该值已更改

因此,通过使用
distinctUntilChanged
,我们可以通过检查源实时数据的值是否已更改来停止无限循环


如果您使用的是livedata ktx库,则可以使用以下代码

init {
   progress.apply { addSource(progressText.distinctUntilChanged()) { postValue(it.toInt()) }}
   progressText.apply { addSource(progress.distinctUntilChanged()) { postValue(it.toString()) }}
}
init {
   progress.apply { addSource(Transformations.distinctUntilChanged(progressText)) { postValue(it.toInt()) }}
   progressText.apply { addSource(Transformations.distinctUntilChanged(progress)) { postValue(it.toString()) }}
}

如果您没有使用livedata ktx库,则可以使用以下代码

init {
   progress.apply { addSource(progressText.distinctUntilChanged()) { postValue(it.toInt()) }}
   progressText.apply { addSource(progress.distinctUntilChanged()) { postValue(it.toString()) }}
}
init {
   progress.apply { addSource(Transformations.distinctUntilChanged(progressText)) { postValue(it.toInt()) }}
   progressText.apply { addSource(Transformations.distinctUntilChanged(progress)) { postValue(it.toString()) }}
}
  • 这里不需要
    MediatorLiveData
    -
    MutableLiveData
    就足够了,因为您只需要能够更改值
  • 对于
    progress
    来说,只有一个
    LiveData
    就足够了,而且里面应该有一个
    Int
  • 现在代码是:

    import androidx.lifecycle.MutableLiveData
    import androidx.lifecycle.ViewModel
    
    open class BasicViewModel: ViewModel() {
        val progress: MutableLiveData<Int> by lazy { MutableLiveData<Int>() }
    }
    
    最后,您的
    活动可以如下所示:

    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
    
            val binding: ActivityMainBinding = DataBindingUtil.setContentView(
                    this, R.layout.activity_main)
            binding.setLifecycleOwner(this)
    
            val viewModel = ViewModelProviders.of(this).get(BasicViewModel::class.java)
            binding.viewModel = viewModel
        }
    }
    
    编辑:

    val progress: MediatorLiveData<Int> by lazy { MediatorLiveData<Int>() }
    val progressText: MediatorLiveData<String> by lazy { MediatorLiveData<String>() }
    
    如果
    EditText
    中的文本与
    SeekBar
    中的值不相同,则方法将不同。然而,有一个
    LiveData
    对象来实现这样的场景仍然足够了。因此,让我们想象一下,
    EditText
    应该显示一个浮点值,如
    progress/100
    。然后,它可以如下所示:

    BasicViewModel.kt

    package com.example.android.databinding.basicsample.data
    
    import androidx.lifecycle.LiveData
    import androidx.lifecycle.MutableLiveData
    import androidx.lifecycle.Transformations
    import androidx.lifecycle.ViewModel
    
    open class BasicViewModel: ViewModel() {
        val progressLiveData = MutableLiveData("0.0")
    
        fun updateEditText(percentage: Int) {
            progressLiveData.value = percentage.toFloat().div(100).toString()
        }
    
        fun onEditTextTyped(): LiveData<Int> {
            return Transformations.switchMap(progressLiveData, {
                val liveData = MutableLiveData<Int>()
                try {
                    liveData.value = it.toString().toFloat().times(100f).toInt()
                } catch (e: NumberFormatException) {
                    // reset the progress bar if the progress text is invalid
                    liveData.value = 0
                }
                liveData
            })
        }
    }
    
    package com.example.android.databinding.basicsample.data
    导入androidx.lifecycle.LiveData
    导入androidx.lifecycle.MutableLiveData
    导入androidx.lifecycle.Transformations
    导入androidx.lifecycle.ViewModel
    开放类BasicViewModel:ViewModel(){
    val progressLiveData=MutableLiveData(“0.0”)
    fun updateEdit文本(百分比:Int){
    progressLiveData.value=percentage.toFloat().div(100).toString()
    }
    fun onEditTextTyped():LiveData{
    返回Transformations.switchMap(progressLiveData{
    val liveData=MutableLiveData()
    试一试{
    liveData.value=it.toString().toFloat().times(100f).toInt()
    }捕获(e:NumberFormatException){
    //如果进度文本无效,请重置进度条
    liveData.value=0
    }
    实时数据
    })
    }
    }
    
    活动\u main.xml

    <layout xmlns:android="http://schemas.android.com/apk/res/android">
        <data>
            <variable
                name="viewModel"
                type="com.example.android.databinding.basicsample.data.BasicViewModel"/>
        </data>
    
        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <androidx.appcompat.widget.AppCompatEditText
                android:id="@+id/input_progress"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="@={viewModel.progressLiveData}" />
    
            <SeekBar
                android:id="@+id/seekbar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:progress="@{viewModel.onEditTextTyped}"
                android:onProgressChanged="@{(seekBar, progress, fromUser) -> viewModel.updateEditText(progress)}" />
    
        </LinearLayout>
    </layout>