java - 与EditText冲突: Watcher to the View + Observer to the MutableLiveData

标签 java android view viewmodel mutablelivedata

我无法理解 Fragment + ViewModel 范例如何与 EditText 等 View 一起使用。

它是一个 EditText,显然会在 View ( fragment )中进行修改。但我也希望能够在 ViewModel 中修改它:例如删除其文本。

这是 Fragment 类中的代码:

public void onActivityCreated(@Nullable Bundle savedInstanceState) {
...
        comment = mViewModel.getComment();
        comment.observe(getViewLifecycleOwner(), new Observer<String>() {
            @Override
            public void onChanged(String s) {
                commentView.setText(s);
            }
        });
...
        commentView.addTextChangedListener(new TextWatcher() {
            @Override
            public void afterTextChanged(Editable s) {
                mViewModel.setComment(String.valueOf(s));
            }
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) { }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) { }
        });

如您所见,我设置了一个观察者,因此当我更改 MutableLiveData 的值时, View 会发生变化。我设置了一个观察者,这样当我(使用应用程序时)更改 View 的值时,MutableLiveData 就会发生变化。

这是 ModelView 类的代码:

public void addRegister() {
...
String comment = this.comment.getValue();
...
this.comment.setValue("");

当我运行应用程序时,没有弹出错误,但它挂起。我猜是因为无限循环。 我应该如何使用此 View + ViewModel 范例来处理 EditTexts?我不明白什么?

提前非常感谢!

最佳答案

由于接受的答案并不在所有情况下都适合我(当通过 EditText 本身以外的其他方式在 ViewModel 中更改文本时),而且我也不想使用数据绑定(bind),所以我想出了以下解决方案,其中一个标志跟踪由 TextWatcher 启动的更新,并在调用观察者时中断循环:

这是我在 Kotlin 中的代码。 对于 Activity :

class SecondActivity : AppCompatActivity() {

    /** Flag avoids endless loops from TextWatcher and observer */
    private var textChangedByListener = true
    private val viewModel by viewModels<SecondViewModel>()
    private lateinit var binding:SecondActivityBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = SecondActivityBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.editText.addTextChangedListener(object: TextWatcher {
            override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3:     Int) {            }
            override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {                }

            override fun afterTextChanged(editable: Editable?) {
                textChangedByListener = true
                viewModel.editText = editable.toString()
            }

        })
        viewModel.editTextLiveData.observe(this) { text -> setEditTextFromViewModel(text) }
    }

    private fun setEditTextFromViewModel(text: String?) {
        if (!textChangedByListener) {
            //text change was not initiated by the EditText itself, and
            //therefore EditText does not yet contain the new text.
            binding.editText.setText(text)
        } else {
            //Don't move that outside of else, because it would then
            //immediately overwrite the value set by TextWatcher
            //which is triggered by the above setText() call.
            textChangedByListener = false
        }
    }

}

为了完整起见,还有 ViewModel:

class SecondViewModel() : ViewModel()
{
    var editText: String
        get() {
            return editTextLiveData.value ?: "InitialLiveData"
        }
        set(value) {
            editTextLiveData.value = value
        }

    var editTextLiveData = MutableLiveData<String>()
}

以防万一,您不熟悉 View 绑定(bind):您可以替换

binding.editText

findViewById(R.id.editTextId) 作为 EditText

关于java - 与EditText冲突: Watcher to the View + Observer to the MutableLiveData,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59875950/

相关文章:

java - 使用spring data jpa设计父子关系的层次结构

java - 动态贾斯珀 : 3 report sections in one page

android - 何时会再次执行 oneOffTaks 结果 GcmNetworkManager.RESULT_RESCHEDULE

android - 使用 MediaPlayer 同时播放多个音频

mysql - 是否可以重命名 View 中的列?

android - Android AppWidget 中的分线器

android - 有时 listView.getChildAt(int index) 返回 NULL (Android)

java - 运行代码时出错(数组问题)?

java - 从 SQLite 数据库中检索图像并显示在 ListView 中

javascript - 未定义不是 this.state 中的对象 - React Native