如何从EditText获取LiveData值并使用Kotlin在TextView中显示它? MVVM

问题描述

概述:

问候。在我的应用程序中,用户可以在EditText中输入一个数字,然后将该数字用作生成从1到(用户输入的数字)的随机数的最大范围,然后应在TextView中显示该数字。

问题:

当用户输入数字并按下按钮以在TextView中生成随机数时,该数字将无法正常工作。

例如:

最初,LiveData为//div[@class='g']//div[@class='r']/a[contains(@href,'https://www.linkedin.com')] 保留的值应为 1 (基于bonusNumber块),但是当按下按钮以显示按下按钮以生成随机数后,将显示随机数 0 ,而不是介于1和用户在EditText中输入的任何数字之间的实际随机数。

代码:

ViewModel:

init

片段:

class QuickPickViewModel : ViewModel() {

    private val repository = Repository()

    // LiveData for the number entered by the user
    private var _userBonusNumber = MutableLiveData<Int>()
    val userBonusNumber: LiveData<Int>
        get() = _userBonusNumber

    // LiveData for the actual result of the randomly generated bonus number
    private var _bonusNumber = MutableLiveData<Int>()
    val bonusNumber: LiveData<Int>
        get() = _bonusNumber

    init {
        _userBonusNumber.value = 1
        _bonusNumber.value = 1
    }

    fun getRandomBonusNumber() {
        // Set the MutableLiveData to be displayed in the TextView,to the number the user entered
        _bonusNumber.value = repository.generateBonusRandomNumber(_userBonusNumber.value!!.toInt())
    }
}

XML视图(相关视图):

class QuickPickFragment : Fragment() {

    private lateinit var binding: FragmentQuickPickBinding
    private lateinit var viewModel: QuickPickViewModel

    override fun onCreateView(
        inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment using data binding
        binding = DataBindingUtil.inflate(
            inflater,R.layout.fragment_quick_pick,container,false
        )

        viewModel = ViewModelProvider(this).get(QuickPickViewModel::class.java)
        
        binding.quickPickViewModel = viewModel
        binding.lifecycleOwner = this

        return binding.root
    }
}

存储库:

 <TextView
                    android:id="@+id/bonus_result_text_view"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="16dp"
                    android:text="@{String.valueOf(quickPickViewModel.bonusNumber)}"
                    android:textAllCaps="true"
                    android:textStyle="bold"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintHorizontal_bias="0.498"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toBottomOf="@+id/main_result_text_view" />

    <EditText
                    android:id="@+id/bonus_set_edit_text"
                    android:layout_width="120dp"
                    android:layout_height="wrap_content"
                    android:layout_margin="16dp"
                    android:layout_marginStart="8dp"
                    android:layout_marginEnd="16dp"
                    android:ems="10"
                    android:hint="@string/enter_number_quick_pick_bonus_edit_text_hint"
                    android:importantForAutofill="no"
                    android:inputType="number"
                    android:text="@{String.valueOf(quickPickViewModel.userBonusNumber)}"
                    app:layout_constraintBaseline_toBaselineOf="@+id/bonus_set_title_text_view"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintStart_toEndOf="@+id/bonus_set_title_text_view" />

     <Button
                    android:id="@+id/button"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="16dp"
                    android:layout_marginEnd="16dp"
                    android:layout_marginBottom="16dp"
                    android:onClick="@{() -> quickPickViewModel.getRandomBonusNumber()}"
                    android:text="Generate"
                    android:textAllCaps="true"
                    android:textStyle="bold"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintStart_toStartOf="parent" />

解决方法

解决方案:

如@AppDev的评论所建议,我可以使用双向数据绑定。

我之前的代码:

android:inputType="number"
android:text="@{String.valueOf(quickPickViewModel.userBonusNumber)}"

应更改为:

android:inputType="number"
android:text="@={quickPickViewModel.userBonusNumber}"

然后我的ViewModel应该更新如下:

class QuickPickViewModel : ViewModel() {
            
  private val repository = Repository()
                     
  val userBonusNumber = MutableLiveData<String>()
                    
  private var _bonusNumber = MutableLiveData<Int>()
  val bonusNumber: LiveData<Int>
    get() = _bonusNumber
            
  init {
    userBonusNumber.value = "1"
    _bonusNumber.value = 1
       }
            
  fun getRandomBonusNumber() {
      _bonusNumber.value = 
      repository.generateBonusRandomNumber(userBonusNumber.value!!.toInt())
   }
}
     

注意:

如评论中所述,两种方式的数据绑定并不总是安全的,因为它公开了具有写功能的实际MutableLiveData,而LiveData是只读且更安全的,但是在我的情况下,这并不适用,因为如前所述,数据是只读的,用户输入的数据不会更改。多亏了这些评论,我才意识到自己的错误。

因此,使用Fragment中的绑定对象从EditText捕获值,然后将TextView设置为该值,会更安全。但是,对于我上面的解决方案,我只是采用了两种方式进行数据绑定以显示其效果,因为Kotlin的在线示例并不多。

仅考虑未来的读者,我将保留所有这些信息。保重。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...