47

假设我使用语句定义了一些变量int someVariable;。代码运行时,变量的值会发生变化。

我如何跟踪这个变量的变化?如何实现一些行为类似于 onSomeVariableChangedListener 的侦听器?

我还需要知道一个页面中的其他方法何时执行,以便我可以在另一个类中设置侦听器。

4

5 回答 5

40

Java 为此类事情提供了一个简单的观察者模式实现,但您需要在管理侦听器通知的方法中设置观察到的变量。如果你不能扩展 Observable,你可以使用组合(即,在你的类中有一个 Observable 实例来管理通知),或者你可以看看 java.util.Observable 来了解如何滚动你自己的版本。

通量.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;
  }
}

赫拉克利特.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);
  }
}
于 2013-03-15T14:00:56.123 回答
34

这是将变量隐藏在setter/getter对后面的众多原因之一。然后,在设置器中,您可以通知您的侦听器该变量已以适当的方式修改。正如其他人所评论的那样,没有内置的方法可以完全按照您的意愿进行操作,您需要自己实现它。

或者,Benjamin 提出了一个有趣的模式,称为装饰器模式,如果相关代码无法修改,它可能对您有用。您可以在 Wikipedia 上查找更多信息

这个想法是围绕一个对象构建一个兼容的包装器。假设您的对象是 MyClass 类型。

class MyClass{
    public void doFunc(){...}
}
    
class MyLoggedClass extends MyClass{
    MyClass myObject;
    
    public void doFunc(){
        //Log doFunc Call
        myObject.doFunc();
    }
}

代替

MyClass object = new MyClass();

你会用

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

现在您的其余代码将照常使用对象,除了每个函数调用将被记录或通知等。

正如您将在 Wikipedia 中看到的那样,这通常是通过相关类继承的接口完成的,但在您的情况下这可能是不可能的。

于 2013-03-15T13:40:44.347 回答
4

您可以使用视图模型。首先创建一个扩展视图模型的类。我打电话给我的 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);

我使用 postValue() 因为我想从工作线程更新变量,如果你在 UI 线程上,你应该使用 setValue()。现在每次更改变量时都会更新 UI。

于 2018-09-22T13:22:23.990 回答
3

我相信您将不得不实施观察者模式

于 2013-03-15T13:38:42.987 回答
1

如果任意变量的值发生更改或调用了某个方法,Java 中没有内置方法来获取通知。

于 2013-03-15T13:37:50.257 回答