javafxで親プロパティが変更されたときに、バインディングをクリーンアップし、ネストされたプロパティのリスナーを変更します

geometrikal

SimpleXXXXPropertyプロパティを持つモデルクラスがあります。Javafx GUI要素は、バインディングまたは変更リスナーのいずれかを使用して更新されます。

textField.textProperty().bind(myModel.myModelStatus());

または

myModel.myModelStatus().addListener((obj,oldv.newv) -> { update here });

モデルクラスのインスタンスが変更されたら、コントロールを再バインドして、リスナーを再度追加します。ただし、メモリの使用により、古いモデルがまだメモリに残っていることがわかります。

モデルへのすべての参照を削除してクリーンアップできるようにするには、どうすればよいですか?

  • 再度バインドする前にバインドを解除します
  • リスナーを削除します
  • 両方とも

親プロパティが変更されたときに、ネストされたプロパティのバインディングとリスナーを更新するより自動化された方法はありますか?

isnot2bad

モデルへのバインディング(リスナーを含む)を元に戻すときに考慮すべきポイント:

  • 無方向バインディング(p1.bind(p2))は、同じプロパティを再度バインドするときに自動的にバインド解除されます(たとえばp1.bind(p3))が、明示的にバインドしても問題はありません(p1.unbind())。
  • 双方向バインディング(p1.bindBidirectional(p2)またはBindings.bindBidirectional(p1, p2))は、明示的に(p1.unbindBidirectional(p2)またはBindings.unbindBidirectional(p1, p2)バインド解除する必要があります
  • リスナーは登録を解除する必要があります(prop.removeListener(l))。

3つ目は、リスナーがラムダ式またはメソッド参照として実装されることが多いため、注意が必要な部分です。残念ながら、ラムダ式とメソッド参照(!)は定数ではありません

// lambdas are not constant
InvalidationListener l1 = obs -> {};
InvalidationListener l2 = obs -> {};

assert l1 != l2; // they are NOT identical!

まあ、これはラムダにとっては明らかかもしれませんが、メソッド参照についても同じことが言えます。これは本当に厄介です。

// method references are not constant
Runnable runnable1 = this::anyMethod;
Runnable runnable2 = this::anyMethod;

assert runnable1 != runnable2; // they are NOT identical!

つまり、ラムダ式または単純なメソッド参照をリスナーとして登録解除できるようにする場合は、それを登録できません。

// if you register listeners on a property like that...
label.textProperty().addListener(obs -> System.out.println(obs));
label.textProperty().addListener(this::handleLabelInvalid);

// ...these calls WON'T remove them due to the inequality shown above!
label.textProperty().removeListener(obs -> System.out.println(obs));
label.textProperty().removeListener(this::handleLabelInvalid);

解決

ラムダ式またはメソッド参照への参照を自分で保存する必要があります。私はそのために最終フィールドを使用するために使用します:

public class MyClass {
    // store references for adding/removal
    private final InvalidationListener l1 = this::handleLabelInvalid;
    private final InvalidationListener l2 = obs -> System.out.println(obs);

    ...

    public void bind() {
        label.textProperty().addListener(l1);
        label.textProperty().addListener(l2);
    }

    public void unbind() {
        label.textProperty().removeListener(l1);
        label.textProperty().removeListener(l2);
    }

    private void handleLabelInvalid(Observable observable) { ... }
}

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ