Android双向数据绑定观察者称为两次

时间:2019-03-19 19:36:36

标签: android android-databinding android-jetpack two-way-binding mutablelivedata

我正在从以下示例中学习使用数据绑定:

https://github.com/ResoCoder/databinding-with-livedata-tutorial

特别是,我在使用以下代码时遇到了麻烦:

https://github.com/ResoCoder/databinding-with-livedata-tutorial/blob/master/app/src/main/java/com/resocoder/databinding/MainActivity.kt

第29行有一个吐司:

Toast.makeText(this,it,Toast.LENGTH_SHORT).show()

如果以编程方式更改editTextContent,则将两次调用该吐司。您可以通过按下标记为“从EDITTEXT中选择随机果”的按钮来重现此行为

在此示例中,两次调用观察者是很浪费的,因为它两次显示了Toast,但是在我使用相同功能的应用程序中,这给用户带来了严重的问题,因为如果通过编程方式对用户进行数据更改,我将执行不同的操作。

我试图通过将状态标记为编程更改来缓解此问题,但是在我的代码完成之后,第二次调用来了。该呼叫似乎就像用户正在编辑文本一样,因此我的程序就像用户输入数据一样执行操作。我看不出有什么方法可以区分外部呼叫和输入数据的用户之间的区别。

请不要建议我隐藏条目的值,如果它没有变化,请忽略无关的调用。有一个合法的用例,其中用户在字段中键入完全相同的值。

理想情况下,找出不必要的呼叫原因并消除它,最好同时解决问题并提高效率。不太理想的解决方法是,因此我可以忽略第二个调用,因此我的代码可以正常工作。

我怀疑这与设置适配器或可能在何时/何地设置观察者有关,但这只是一个猜测。

谢谢。

1 个答案:

答案 0 :(得分:0)

  • 这是我做事的结果
  • GIF imgur
  • 提供支持

Gif ==>如何做到

  1. 我的库的实现core_android module,当然不是整个库也不是模块 只是针对该问题,但如您在上面的gif中看到的那样,它包括该问题的解决方案。

  2. 在activity_main.xml中

<!-- use the below 2 attributes
1st one ensures single trigger & 2nd one to distinguish the change -->
<EditText
    editText_textTwoWay="@={viewModel.mutableLiveDataEditTextContent}"
    editText_textTwoWay_enableDistinguishChangeCauser="@{true}"/>
  1. 在MainActivity.kt
// inside onCreate()

// for dynamic change -> on button click
button.setOnClickListener {
    viewModel.mutableLiveDataEditTextContent.value = "Hello"
}

// for observing the change -> observe live data
viewModel.mutableLiveDataEditTextContent.observe(this, Observer {
    val isUserInputChangeNotDynamicallyChanged = binding.editText
        .getTag(R.id.editText_textTwoWay_isUserInputChangeNotDynamicallyChanged) as? Boolean
    val prefixMsg = when (isUserInputChangeNotDynamicallyChanged) {
        true -> {
            "User Change -> "
        }
        false -> {
            "Dynamic Change -> "
        }
        null -> {
            "UNKNOWN Change -> "
        }
    }
    val msg = prefixMsg + it.toStringOrEmpty()
    toast(msg) // extension fun for showing a Toast
    logError(msg) // to ensure invocation is done once isa.
})