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

My app doesn't show LiveData<String> into a text

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
    }
}
StartFragment

XML

<com.google.android.material.textfield.TextInputLayout
                android:id="@+id/player_one_name"
                style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
                android:layout_width="180dp"
                android:layout_height="wrap_content"
                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_width="match_parent"
                    android:layout_height="wrap_content"
                    android:inputType="text"
                    android:maxLines="1" /> 

XML 对于 GameFragment

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

GameFragment

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,但正如我所料,同样的问题是视图模型 class

中 Log.d 的代码
        Log.d("GameViewModel", _playerOneScore.value.toString() + " Score: " + playerOneScore.value)

这是 logcat

D/GameViewModel: 0 Score: null

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

Gradle 文件

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

ViewModel

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
    }
}

GameFragment

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")

}

在 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) }

对于玩家的得分,我做了以下操作

ViewModel

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()}"