我的应用程序没有在文本中显示 LiveData<String>

Posted

技术标签:

【中文标题】我的应用程序没有在文本中显示 LiveData<String>【英文标题】:My app doesn't show LiveData<String> into a text 【发布时间】:2022-01-16 10:25:21 【问题描述】:

LiveData 应该打印我们之前从 TextInputEditText 获取的 playerOneName 文本属性中的字符串,但我什至在 Log.d 中尝试过它根本没有显示任何结果。

这是代码ViewModel

class GameViewModel: ViewModel() 
    private val _playerOne = MutableLiveData<String>()
    val playerOne: LiveData<String> = _playerOne
    private val _playerTwo = MutableLiveData<String>()
    val playerTwo: LiveData<String> = _playerTwo
    private val _playerOneScore = MutableLiveData<Int>(0)
    val playerOneScore: LiveData<Int> = _playerOneScore
    private val _playerTwoScore = MutableLiveData<Int>(0)
    val playerTwoScore: LiveData<Int> = _playerTwoScore

    fun setPlayerOne(name: String) 
        _playerOne.value = name
    

    fun setPlayerTwo(name: String) 
        _playerTwo.value = name
    

XML 的 StartFragment

<com.google.android.material.textfield.TextInputLayout
                android:id="@+id/player_one_name"
                style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
                android:layout_
                android:layout_
                android:hint="@string/player_one_name"
                android:paddingStart="8dp"
                android:paddingTop="8dp"
                android:paddingEnd="10dp"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toBottomOf="@id/start_img">

                <com.google.android.material.textfield.TextInputEditText
                    android:id="@+id/edit_player_one"
                    android:layout_
                    android:layout_
                    android:inputType="text"
                    android:maxLines="1" /> 

XML 用于 GameFragment

<TextView
            android:id="@+id/player_one_name"
            android:layout_
            android:layout_
            android:layout_marginBottom="4dp"
            android:text="@viewModel.playerOne.toString()"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

游戏片段

class GameFragment : Fragment() 

    private var _binding: FragmentGameBinding? = null
    private val binding get() = _binding!!
    private val sharedViewModel: GameViewModel by activityViewModels()

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? 
        _binding = FragmentGameBinding.inflate(inflater, container, false)
        binding.resetBtn.setOnClickListener 
            findNavController().navigate(R.id.action_gameFragment_to_startFragment)
        
        return binding.root
    

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) 
        super.onViewCreated(view, savedInstanceState)
        binding.apply 
            lifecycleOwner = viewLifecycleOwner
            viewModel = sharedViewModel
            gameFragment = this@GameFragment
        
        Log.d("GameFragment", "Player One:" + sharedViewModel.playerOne.toString())
    

我尝试了 playerOneScore,但正如我所料,这是同样的问题,这是 viewModel 类中 Log.d 的代码

        Log.d("GameViewModel", _playerOneScore.value.toString() + " Score: " + playerOneScore.value)

这是日志猫

D/GameViewModel: 0 Score: null

【问题讨论】:

在此处尝试不使用 toString() android:text="@viewModel.playerOne" 。也用于 Log 使用,例如 sharedViewModel.playerOne.value。 尝试不使用 toString() 但仍然是同样的问题。 xml中不需要toString(),类中使用sharedViewModel.playerOne.value 还是同样的问题 【参考方案1】:

试试下面的代码希望能解决你的问题

Gradle 文件

    implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.0'
    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0'

视图模型

class GameViewModel: ViewModel() 
    private val _playerOne = MutableLiveData<String>()
    val playerOne: LiveData<String> = Transformations.map(_playerOne)  it   
    private val _playerTwo = MutableLiveData<String>()
    val playerTwo: LiveData<String> =  Transformations.map(_playerTwo)  it 
    private val _playerOneScore = MutableLiveData<Int>(0)
    val playerOneScore: LiveData<Int> = Transformations.map(_playerOneScore)  it 
    private val _playerTwoScore = MutableLiveData<Int>(0)
    val playerTwoScore: LiveData<Int> = Transformations.map(_playerTwoScore)  it 

    fun setPlayerOne(name: String) 
        _playerOne.value = name
    

    fun setPlayerTwo(name: String) 
        _playerTwo.value = name
    

游戏片段

class GameFragment : Fragment() 

private lateinit var sharedViewModel: GameViewModel 

override fun onViewCreated(view: View, savedInstanceState: Bundle?) 
    super.onViewCreated(view, savedInstanceState)
    
sharedViewModel= ViewModelProvider(this).get(GameViewModel::class.java)
sharedViewModel.playerOne.observe(viewLifecycleOwner)   
    Log.d("GameFragment", "Player One: $it")
 

// use this method to change the value
   sharedViewModel.setPlayerOne("Some Player")


【讨论】:

仍然遇到同样的问题,我已经编辑了问题以显示 Log.d【参考方案2】:

在 StartFragment.kt 中,您需要重写 onPause() 函数,这样当您转到下一个片段时,它会将玩家的名称保存在 ViewModel 中。

StartFragment.kt

override fun onPause() 
    super.onPause()
    var playerOneName: String = binding.editPlayerOne.text.toString()
    sharedViewModel.setPlayerOne(playerOneName)
    var playerTwoName: String = binding.editPlayerTwo.text.toString()
    sharedViewModel.setPlayerTwo(playerTwoName) 

为了玩家的分数,我做了以下操作

视图模型

init 
    resetData()

fun playerOneWon() 
    _playerOneScore.value = _playerOneScore.value?.plus(1)

fun playerTwoWon() 
    _playerTwoScore.value = _playerTwoScore.value?.plus(1)
fun resetData() 
    _playerOneScore.value = 0
    _playerTwoScore.value = 0 

我使用 playerOneWon()playerTwoWon() 函数来增加 GameFragment.kt 和我使用的 xml 中的分数

android:text="@viewModel.playerOneScore.toString()"

【讨论】:

以上是关于我的应用程序没有在文本中显示 LiveData<String>的主要内容,如果未能解决你的问题,请参考以下文章

LiveData 观察()未调用

在 Android 视图模型中的内部网络更改回调时 LiveData 未触发 - Kotlin

使用 LiveData 时检查 RoomDatabase 是不是为空

子线程频繁更新ui导致界面卡顿问题?

如何在 Activity 中使用 Room 和 LiveData 删除 LiveData<Object>?

带有TextWatcher和LiveData的EditText中的光标位置?