Transformations.distinctUntilChanged()配合重写equals()不生效如何解决
问题根因
- 你在MainActivity中全局复用了同一个
MyInteger实例,每次点击仅修改该实例的内部数值后直接传给LiveData。distinctUntilChanged比较新旧值时会首先触发equals方法的if (this == o) return true判断,直接判定两个值完全相同,因此从第二次点击开始就不会触发回调。 - 现有
equals方法的边界判断逻辑存在缺陷,无法正确实现“数值超过5后判定为相同”的需求。
修复方案
1. 修改MainActivity逻辑,每次传入新的MyInteger实例
不要复用同一个MyInteger对象,每次点击都创建新实例传递给LiveData,避免引用相等直接判定为相同:
public class MainActivity extends AppCompatActivity { private MainActivityViewModel mMainActivityViewModel; Button button; // 改用基础类型存储当前计数,避免复用自定义对象 private int currentCount = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button = findViewById(R.id.my_button); mMainActivityViewModel = new ViewModelProvider(this).get(MainActivityViewModel.class); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { currentCount++; // 每次创建新的MyInteger实例传入 mMainActivityViewModel.getLiveData().setValue(new MyInteger(currentCount)); } }); Transformations.distinctUntilChanged(mMainActivityViewModel.getLiveData()).observe(this, new Observer<MyInteger>() { @Override public void onChanged(MyInteger myInteger) { Log.wtf("Transformations onChanged:", String.valueOf(myInteger.integer)); Toast.makeText(MainActivity.this, "Transformations onChanged:"+String.valueOf(myInteger.integer), Toast.LENGTH_SHORT).show(); } }); } }
2. 重写MyInteger的equals方法,匹配需求逻辑
调整equals实现,满足:只要任意一个实例数值超过5,就判定为相同;否则仅当数值相等时判定为相同:
public class MyInteger { public int integer; public MyInteger(Integer integer) { this.integer = integer; } public void incrementByOne() { integer++; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; MyInteger myInteger = (MyInteger) o; // 只要任意一个值超过5,就判定为相同,不再触发回调 if (this.integer > 5 || myInteger.integer > 5) { return true; } // 5及以下仅当数值相等时判定为相同 return this.integer == myInteger.integer; } @Override public int hashCode() { return Objects.hash(integer); } }
效果验证
修改后运行效果完全匹配预期:
- 点击1-5次时,每次数值都≤5且前后值不同,
equals返回false,触发Toast弹出 - 第6次及以后点击时,数值超过5,
equals返回true,不再触发Toast
内容的提问来源于stack exchange,提问作者mars8
相关产品推荐
相关产品推荐

