web-dev-qa-db-ja.com

変数の変更リスナーを作成する方法は?

Statementint someVariable;を使用して定義された変数があるとします。コードの実行中に、変数の値が変更されます。

この変数の変更を追跡するにはどうすればよいですか? onSomeVariableChangedListenerのように動作するリスナーを実装するにはどうすればよいですか?

また、あるページの他のメソッドがいつ実行されたかを知る必要があるため、別のクラスにリスナーを設定できます。

39
Sinigami

これは、変数をsetter/getterペアの後ろに隠す多くの理由の1つです。その後、セッターで、この変数が適切な方法で変更されたことをリスナーに通知できます。他の人がコメントしたように、あなたが望むことを正確に行うための方法が組み込まれていないので、自分で実装する必要があります。

あるいは、BenjaminがDecoratorパターンと呼ばれる興味深いパターンを表示します。これは、問題のコードを変更できない場合に役立ちます。 ウィキペディアで詳細を調べることができます

アイデアは、オブジェクトの周りに互換性のあるラッパーを構築することです。問題のオブジェクトがMyClass型であるとしましょう。

class MyClass{
   publc void doFunc(){...}
}

class MyLoggedClass extends MyClass{
    MyClass myObject;

    publc void doFunc(){
        //Log doFunc Call

       myObject.doFunc();

    }
}

の代わりに

MyClass object = new MyClass();

あなたは使うだろう

MyClass object = new MyLoggedClass(new MyClass());

これで、残りのコードは通常どおりオブジェクトを使用しますが、各関数呼び出しはログに記録されるか、通知されるなどです。

ウィキペディアで見るように、これは通常、問題のクラスが継承するインターフェイスを介して行われますが、これは不可能な場合があります。

29
Karthik T

Javaはこの種の単純なObserverパターン実装を提供しますが、リスナー通知を管理するメソッド内で監視変数を設定する必要があります。 Observableを拡張できない場合は、コンポジションを使用する(つまり、通知を管理するためにクラスにObservableインスタンスを用意する)か、Java.util.Observableを見て、独自のロール方法を理解することができます版。

Flux.Java

import Java.util.Observable;

public class Flux extends Observable {
  private int someVariable = 0;

  public void setSomeVariable(int someVariable) {
    synchronized (this) {
      this.someVariable = someVariable;
    }
    setChanged();
    notifyObservers();
  }

  public synchronized int getSomeVariable() {
    return someVariable;
  }
}

Heraclitus.Java

import Java.util.Observable;
import Java.util.Observer;

public class Heraclitus implements Observer {
  public void observe(Observable o) {
    o.addObserver(this);
  }

  @Override
  public void update(Observable o, Object arg) {
    int someVariable = ((Flux) o).getSomeVariable();
    System.out.println("All is flux!  Some variable is now " + someVariable);
  }
}
35
Kevin Condon

Observer Pattern を実装する必要があると思います。

3

ビューモデルを使用できます。最初に、ビューモデルを拡張するクラスを作成します。私はNameViewModelを呼び出しました。

import Android.Arch.lifecycle.MutableLiveData;
import Android.Arch.lifecycle.ViewModel;

public class NameViewModel extends ViewModel {
private MutableLiveData<String> currentName;

public MutableLiveData<String> getCurrentName(){
        if(currentName == null){
            currentName = new MutableLiveData<>();
        }
        return currentrName;
    }
}

次に、アクティビティで変数値を変更すると、まずNameViewModelクラスのインスタンスが定義されます。

private NameViewModel mNameViewModel;

次に、onCreateでこのコードスニペットを使用します

mNameViewModel = ViewModelProvider.of(this).get(NameViewModel.class)
mNameViewModel.getCurrentName().observe(this, new Observer<String>() {
    @Override
    public void onChanged(@Nullable String name) {
        //do what you want when the varriable change.
    }
});

nameの値を変更する場合は、次のコードスニペットを使用できます。

mNameViewModel.getCurrentName().postValue(String newName);

SetValue()を使用する必要があるUIスレッドを使用している場合、ワーカースレッドから変数を更新するため、postValue()を使用します。これで、変数が変更されるたびにUIが更新されます。

1

任意の変数の値が変更された場合、または何らかのメソッドが呼び出された場合に通知を受け取るためのJavaには組み込みの方法はありません。

0
Jesper