我的应用没有在文本中显示 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
}
}
StartFragmentXML
<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()}"
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
}
}
StartFragmentXML
<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()}"