【问题标题】:Why is LiveData onChanged called before data change is made?为什么在进行数据更改之前调用 LiveData onChanged?
【发布时间】:2018-09-09 04:56:34
【问题描述】:

上下文

使用MutableLiveData 来保存一个值。 Button click 应该增加值。

问题

MutableLiveData 的 Observer.onChanged() 似乎在 MutableLiveData.setValue() 用于更改值之前被调用。

例如,在Button点击之前,onChanged日志发生在设置初始值之后(onChanged纳秒大于新值纳秒)。然而,Button 点击后,onChanged 日志发生在新值设置之前(onChanged 纳秒小于新值纳秒)。为什么会这样?:

Button 点击之前(onChanged 日志预计在设置初始值后发生):

09-06 20:30:47.877 com.example.android.test D/TAG: initial set val ns 102107899222617
    initial get val ns 102107899367096
09-06 20:30:47.882 com.example.android.test D/TAG: onChanged integer 0 ns 102107903996992

按钮点击后(onChanged日志意外在设置新值之前发生):

09-06 20:30:55.372 com.example.android.test D/TAG: onChanged integer 1 ns 102115394178238
09-06 20:30:55.373 com.example.android.test D/TAG: onClick set new val 1 ns 102115394446415

代码

final MutableLiveData<Integer> val = new MutableLiveData<>();
val.setValue(0); // triggers onChanged
Log.d(TAG, "initial set val ns " + System.nanoTime());

tv.setText("" + val.getValue());
Log.d(TAG, "initial get val ns " + System.nanoTime());

val.observe(this, new Observer<Integer>() {
    @Override
    public void onChanged(@Nullable Integer integer) {
        // onChanged happens after initial setValue but before setValue with new value
        Log.d(TAG, "onChanged integer " + integer + " ns " + System.nanoTime());
        tv.setText("" + integer);
    }
});

btn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // setting new value (triggers onChanged but 
        // onChanged happens before setting new value via setValue)
        int newVal = val.getValue() + 1;
        val.setValue(newVal);
        Log.d(TAG, "onClick set new val " + newVal + " ns " + System.nanoTime());
    }
});

【问题讨论】:

  • 在调用val.setValue(newVal);之前先调用Log.d(TAG, "onClick set new val " + newVal + " ns " + System.nanoTime());
  • @pskink 有道理,只是想澄清一下onChanged 是在setValue 之后发生的,谢谢
  • 否则你会在灯泡熄灭之前发现一台时光机 ;-)
  • @pskink 很好的类比;)另外,要结束这个问题,我应该添加编辑作为答案,留下它,还是不需要接受的答案?
  • 你可以自己写答案

标签: java android android-livedata mutablelivedata


【解决方案1】:

正如@pskink 指出的那样,问题在于设置新值的日志位置,在MutableLiveValue.setValue() 明确之前和之后记录:

在日志前后添加:

final MutableLiveData<Integer> val = new MutableLiveData<Integer>() {
    @Override
    public void setValue(Integer value) {
        Log.d(TAG, "setValue before");
        super.setValue(value);
        Log.d(TAG, "setValue after");
    }
};

在Button点击之后(onChanged日志预计在setValue之后发生):

09-06 20:52:02.869 com.example.android.test D/TAG: onClick: before set new val
    setValue before
09-06 20:52:02.870 com.example.android.test D/TAG: onChanged integer 1 ns 103382891472200
    setValue after
    onClick after set new val 1 ns 103382891671576

编辑

在setValue 之后发生日志记录的原因是在onChanged 之后发生的,因为onChanged 在setValue 中的某个时间点被调用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-18
    • 1970-01-01
    • 1970-01-01
    • 2021-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多