web-dev-qa-db-fra.com

Comment créer un auditeur de changement pour variable?

Disons que j'ai une variable définie en utilisant le statementint someVariable;. Pendant que le code est exécuté, la valeur de la variable change.

Comment puis-je suivre les changements dans cette variable? Comment puis-je implémenter un auditeur qui se comporte comme onSomeVariableChangedListener? 

J'ai également besoin de savoir quand une autre méthode d'une page a été exécutée pour pouvoir définir un auditeur dans une autre classe.

37
Sinigami

C’est l’une des nombreuses raisons de masquer les variables derrière les paires setter/getter. Ensuite, dans le configurateur, vous pouvez informer votre auditeur que cette variable a été modifiée de la manière appropriée. Comme les autres l'ont commenté, il n'y a pas de méthode intégrée pour faire exactement ce que vous voulez, vous devez l'implémenter vous-même.

Sinon, Benjamin propose un motif intéressant, appelé motif Décorateur, qui peut vous être utile si le code en question ne peut pas être modifié. Vous pouvez rechercher plus d'informations sur wikipedia

L'idée est de construire un wrapper compatible autour d'un objet. Disons que votre objet en question est de type MyClass.

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

class MyLoggedClass extends MyClass{
    MyClass myObject;

    publc void doFunc(){
        //Log doFunc Call

       myObject.doFunc();

    }
}

au lieu de 

MyClass object = new MyClass();

Vous utiliseriez 

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

Maintenant, votre reste du code utiliserait l'objet comme d'habitude, sauf que chaque appel de fonction sera consigné, ou notifié, etc.

Comme vous le verrez dans wikipedia, cela se fait généralement via une interface dont la classe en question hérite, mais cela peut ne pas être possible dans votre cas.

28
Karthik T

Java vous donne une implémentation simple de modèle Observer pour ce genre de choses, mais vous devrez définir votre variable observée dans une méthode qui gère les notifications d'écouteur. Si vous ne pouvez pas étendre Observable, vous pouvez utiliser la composition (c’est-à-dire avoir une instance Observable dans votre classe pour gérer les notifications), ou vous pouvez jeter un coup d’œil sur Java.util.Observable pour avoir une idée de la manière de rouler vous-même. version.

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

Je crois que vous devrez implémenter Observer Pattern .

3
Ivaylo Strandjev

Vous pouvez utiliser View Model. Commencez par créer une classe qui étend le modèle de vue. J'ai appelé le mien 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;
    }
}

alors en activité que la valeur de la variable change définit d'abord une instance de votre classe NameViewModel:

private NameViewModel mNameViewModel;

puis dans onCreate, utilisez cet extrait de code 

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.
    }
});

si vous voulez changer la valeur de name, vous pouvez utiliser cet extrait de code:

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

J'utilise postValue () puisque je veux mettre à jour la variable du thread de travail si vous êtes sur le thread de l'interface utilisateur, vous devez utiliser setValue () . Maintenant, chaque fois que la variable est modifiée, l'interface utilisateur est mise à jour.

1
Hamzeh Moghaddam

Il n'y a pas de moyen intégré en Java pour obtenir une notification si la valeur d'une variable arbitraire change ou si une méthode a été appelée.

1
Jesper