我的应用未将实时数据显示<String>为文本



LiveData应该在playerOneName文本属性中打印一个String,我们之前从TextInputEditText中提取了这个属性,但我甚至在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" />

游戏碎片

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)

这是logcat

D/GameViewModel: 0 Score: null

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

渐变文件

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

游戏碎片

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

相关内容

最新更新