我的应用程序没有在文本中显示 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>的主要内容,如果未能解决你的问题,请参考以下文章
在 Android 视图模型中的内部网络更改回调时 LiveData 未触发 - Kotlin
使用 LiveData 时检查 RoomDatabase 是不是为空