您可以使用Transformations.distinctUntilChanged(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()) }}
}
如果您不使用 livedata-ktx 库,则可以使用以下代码
init {
progress.apply { addSource(Transformations.distinctUntilChanged(progressText)) { postValue(it.toInt()) }}
progressText.apply { addSource(Transformations.distinctUntilChanged(progress)) { postValue(it.toString()) }}
}
,
- 这里不需要
MediatorLiveData
-MutableLiveData
就足够了,因为您只需要能够更改值即可。
- 对于
LiveData
只使用一个progress
就足够了,它应该在内部保留一个Int
值。
现在输入代码:
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
open class BasicViewModel: ViewModel() {
val progress: MutableLiveData<Int> by lazy { MutableLiveData<Int>() }
}
您的布局如下所示(请注意,viewModel.progress
是如何将String
转换为EditText
的{{1}})
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="viewModel"
type="BasicViewModel"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText android:id="@+id/input_progress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="numberDecimal"
android:text="@={`` + viewModel.progress}" />
<SeekBar
android:id="@+id/seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:progress="@={viewModel.progress}" />
</LinearLayout>
</layout>
最后,您的Activity
可能如下:
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
}
}
编辑:
如果EditText
中的文本与SeekBar
中的值不同,则方法将有所不同。但是,只要有一个LiveData<charSequence>
对象就可以实现这种情况。因此,假设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
})
}
}
activity_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>
,
您可以分别为搜索者和文本制作2对MediatorLiveData-LiveData。例如,第一个MediatorLiveData观察到搜索栏的变化,并且当应用更改时,它会更改EditText的LiveData,反之亦然:您拥有MediatorLiveData,它在每次EditText中发生更改时都会更改SeekBar的LiveData。
本文链接:https://www.f2er.com/3095226.html