web-dev-qa-db-ja.com

ライブデータと双方向データバインディング:カスタムセッターが呼び出されない

EditTextで設定された文字列を使用して、ViewModelからのLiveData Stringオブジェクトを更新するために双方向データバインディングを使用しています。

<Android.support.design.widget.TextInputEditText
  Android:id="@+id/writeReviewTitle"
  Android:layout_width="match_parent"
  Android:layout_height="wrap_content"
  Android:text="@={viewModel.liveReviewTitle}"
/>

したがって、私の理解では、ViewModelは、EditTextでテキストが変更されるたびにliveReviewTitle属性が更新されます。これは、TextWatcher、またはライブラリーによって処理されているリスニングメカニズムの使用によって発生していると思います。また、テキストを更新する必要がある場合は、setterが呼び出されると考えました。 そうではないようです!テキストが変更されると、ViewModelでさらにいくつかのことを行う必要があるため、setterのカスタムliveReviewTitleを実装しましたが、それは呼び出されていない(Iデバッグを試みました)。これは、ViewModelクラスで次のように表示されます。

var liveReviewTitle: MutableLiveData<String> = MutableLiveData()
        set(value) {
            field = value
            customLogicHere()
        }

これをsetterでデバッグしようとしましたが、呼び出されているようには見えません!ここで何が起きてるの?少し混乱します。テキストは更新され、ViewModelに保存されます。呼び出されないのはsetterだけです。

もちろん、決して呼び出されることはありません。新しいMutableLiveDataを設定するのではなく、MutableLiveData内に新しい文字列値を設定します(おそらくsetValueを使用)。

ただし、MutableLiveDataではなくMediatorLiveDataを直接公開する場合は、設定されている値をインターセプトして、値を設定した後にカスタムロジックを実行できるはずです。

編集:以下は期待どおりに機能するはずです。

val liveReviewTitle: MutableLiveData<String> = MutableLiveData()
private val mediator = MediatorLiveData<String>().apply {
    addSource(liveReviewTitle) { value ->
        setValue(value)
        customLogicHere()
    }
}.also { it.observeForever { /* empty */ } }
6
EpicPandaForce

@EpicPandaForceソリューションは適切ですが、EditTextでは双方向のバインディングをより簡単な方法で取得できます。以下のように、属性afterTextChangedをウィジェットに追加します。

_Android:afterTextChanged="@{viewModel::doLogic}"_

次に、ViewModelクラスにメソッドを書き込むだけです。

fun doLogic(s: Editable) { //update Livedata or do other logic }

[〜#〜]編集[〜#〜]

重要なドキュメントを見逃してしまいました note 。はるかに簡単です(そしてはるかに適切です):

_Android:text="@={viewModel.someLivedata}
_

次に、LifecycleOwnerクラスで、必要に応じてliveDataの値を毎回更新できます。もちろん、登録されたオブザーバーからの変更に対応できます。

3
Karol Kulbaka

@EpicPandaForceはあなたのセッターについて正しいです、それはMutableLiveData自体のためであり、それが保持している値ではありません。したがって、LiveDatavalである必要があり、varである必要はありません。また、LifecycleOwnerバインディング。カスタムセッターの代わりに別のObserverLiveDataに追加して、カスタムロジックを追加できます。

2
Mateo