我有TextInput和SeekBar。
我需要通过文本输入值(数字)更改搜索器的值,并通过搜索器更改的值来更改文本值。使用视图模型和实时数据绑定
所以,我在viewmodel类中有两个调解器实时数据
ViewModel:
val progress: MediatorLiveData<Int> by lazy { MediatorLiveData<Int>() }
val progressText: MediatorLiveData<String> by lazy { MediatorLiveData<String>() }
在init范围内彼此观察。
init {
progress.apply { addSource(progressText) { postValue(it.toInt()) }}
progressText.apply { addSource(progress) { postValue(it.toString()) }}
}
并且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}" />
但是,在这里,我陷入了无限循环,因为一个调解人的改变会影响到另一个调解人,而另一个的改变又回到了另一个。
这里是否有最佳实践和更巧妙的解决方案来解决此逻辑?谢谢。
您可以分别为搜索者和文本制作2对MediatorLiveData-LiveData。例如,第一个MediatorLiveData观察到搜索栏的变化,并且当应用更改时,它会更改EditText的LiveData,反之亦然:您有MediatorLiveData,每次在EditText中进行更改时,它都会更改SeekBar的LiveData。
您可以使用Transformations.distinctUntilChanged(liveData)
创建一个新的LiveData对象,直到更改了源LiveData值后,该对象才发出值。如果equals()得出false,则认为该值已更改。
因此,通过使用Transformations.distinctUntilChanged(liveData)
,我们可以通过检查源实时数据的值是否已更改来停止无限循环。
如果使用的是livedata-ktx库,则可以使用以下代码
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()) }}
}
-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
最后,您的<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