两个中介实时数据互相观察

问题描述 投票:0回答:3

我有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}" />

enter image description here(考虑输入文字)

但是,在这里,我陷入了无限循环,因为一个调解人的改变会影响到另一个调解人,而另一个的改变又回到了另一个。

这里是否有最佳实践和更巧妙的解决方案来解决此逻辑?谢谢。

android kotlin mvvm viewmodel android-livedata
3个回答
0
投票

您可以分别为搜索者和文本制作2对MediatorLiveData-LiveData。例如,第一个MediatorLiveData观察到搜索栏的变化,并且当应用更改时,它会更改EditText的LiveData,反之亦然:您有MediatorLiveData,每次在EditText中进行更改时,它都会更改SeekBar的LiveData。


0
投票

您可以使用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()) }}
}

0
投票
  1. 这里您不需要init { progress.apply { addSource(Transformations.distinctUntilChanged(progressText)) { postValue(it.toInt()) }} progressText.apply { addSource(Transformations.distinctUntilChanged(progress)) { postValue(it.toString()) }} } -MediatorLiveData就足够了,因为您只需要能够更改值。
  2. 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
© www.soinside.com 2019 - 2024. All rights reserved.