Fragment class、MVVM、Viewmodel 中未解析的引用 (vars)
Unresolved reference (vars) in Fragment class, MVVM, Viewmodel
我正在学习关于使用 Kotlin 开发 Android 应用程序的 UDACITY 免费课程,实际上我在课程的 Viewmodel/MVVM 部分,即实现视图模型 classes更好地分离关注点。所以无论如何,我现在被阻止了。我正在进行的练习是关于创建 Viewmodel class 并将变量和函数从 Fragment class 传输到这个新创建的 class。我一步一步地按照教程,在提供的 git diff 上检查正确答案,但我仍然发现自己被未解决的引用错误阻止了。
在更改代码之前,我必须更新我的 Gradle 模块文件以使用 ViewModel
//ViewModel
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
然后我不得不在我的 Fragment 中声明我的 Viewmodel 对象 class
gameViewModel = ViewModelProviders.of(this).get(GameViewModel::class.java)
ViewModelProviders 被弃用,旧课程,我不得不在搜索后更改为
gameViewModel = ViewModelProvider(this).get(GameViewModel::class.java)
这似乎是正确的做法,但我仍然对变量 word (gameViewModel.word) 和 score (gameViewModel.score) 在 Fragment class 中,无法编译。我不知道我是否正确声明了 Viewmodel 对象,或者我是否遗漏了其他东西...
我没有这个问题,未解决的参考,我的 ViewModel class 函数,即 gameViewModel.onCorrect() 和 gameViewModel.onSkip()。它们似乎在片段 class 中被正确声明和调用,这让我对我的变量、单词和分数提出了问题...
我的片段class
package com.example.android.guesstheword.screens.game
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.NavHostFragment.findNavController
import com.example.android.guesstheword.R
import com.example.android.guesstheword.databinding.GameFragmentBinding
import timber.log.Timber
class GameFragment : Fragment() {
private lateinit var binding: GameFragmentBinding
private lateinit var gameViewModel: GameViewModel
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate view and obtain an instance of the binding class
binding = DataBindingUtil.inflate(
inflater,
R.layout.game_fragment,
container,
false
)
Timber.i("onCreateView GameFragment called")
gameViewModel = ViewModelProvider(this).get(GameViewModel::class.java)
Timber.i("ViewModelProvider is called")
binding.correctButton.setOnClickListener {
gameViewModel.onCorrect()
updateScoreText()
updateWordText()
}
binding.skipButton.setOnClickListener {
gameViewModel.onSkip()
updateScoreText()
updateWordText()
}
updateScoreText()
updateWordText()
return binding.root
}
/**
* Called when the game is finished
*/
fun gameFinished() {
val action = GameFragmentDirections.actionGameToScore(gameViewModel.score)
findNavController(this).navigate(action)
}
/** Methods for updating the UI **/
private fun updateWordText() {
binding.wordText.text = gameViewModel.word
}
private fun updateScoreText() {
binding.scoreText.text = gameViewModel.score.toString()
}
override fun onDestroyView() {
super.onDestroyView()
Timber.i("onDestroyView GameFragment called")
}
}
我的视图模型class
package com.example.android.guesstheword.screens.game
import androidx.lifecycle.ViewModel
import timber.log.Timber
var word = ""
var score = 0
private lateinit var wordList: MutableList<String>
class GameViewModel: ViewModel() {
init {
Timber.i("GameViewModel is created")
resetList()
nextWord()
}
override fun onCleared() {
super.onCleared()
Timber.i("GameViewModel is cleared")
}
/**
* Resets the list of words and randomizes the order
*/
fun resetList() {
wordList = mutableListOf(
"queen",
"hospital",
"basketball",
"cat",
"change",
"snail",
"soup",
"calendar",
"sad",
"desk",
"guitar",
"home",
"railway",
"zebra",
"jelly",
"car",
"crow",
"trade",
"bag",
"roll",
"bubble"
)
wordList.shuffle()
}
/**
* Moves to the next word in the list
*/
private fun nextWord() {
//Select and remove a word from the list
if (wordList.isEmpty()) {
//gameFinished()
} else {
word = wordList.removeAt(0)
}
}
/** Methods for buttons presses **/
fun onSkip() {
score--
nextWord()
}
fun onCorrect() {
score++
nextWord()
}
}
我哪里搞砸了?
您尝试访问的变量不属于同一范围:
var word = ""
var score = 0
private lateinit var wordList: MutableList<String>
class GameViewModel: ViewModel() {
...
您的变量在 ViewModel 外部声明,将它们添加到 class GameViewModel
中以使其成为实例变量:
class GameViewModel: ViewModel() {
var word = ""
var score = 0
...
}
我正在学习关于使用 Kotlin 开发 Android 应用程序的 UDACITY 免费课程,实际上我在课程的 Viewmodel/MVVM 部分,即实现视图模型 classes更好地分离关注点。所以无论如何,我现在被阻止了。我正在进行的练习是关于创建 Viewmodel class 并将变量和函数从 Fragment class 传输到这个新创建的 class。我一步一步地按照教程,在提供的 git diff 上检查正确答案,但我仍然发现自己被未解决的引用错误阻止了。
在更改代码之前,我必须更新我的 Gradle 模块文件以使用 ViewModel
//ViewModel
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
然后我不得不在我的 Fragment 中声明我的 Viewmodel 对象 class
gameViewModel = ViewModelProviders.of(this).get(GameViewModel::class.java)
ViewModelProviders 被弃用,旧课程,我不得不在搜索后更改为
gameViewModel = ViewModelProvider(this).get(GameViewModel::class.java)
这似乎是正确的做法,但我仍然对变量 word (gameViewModel.word) 和 score (gameViewModel.score) 在 Fragment class 中,无法编译。我不知道我是否正确声明了 Viewmodel 对象,或者我是否遗漏了其他东西...
我没有这个问题,未解决的参考,我的 ViewModel class 函数,即 gameViewModel.onCorrect() 和 gameViewModel.onSkip()。它们似乎在片段 class 中被正确声明和调用,这让我对我的变量、单词和分数提出了问题...
我的片段class
package com.example.android.guesstheword.screens.game
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.NavHostFragment.findNavController
import com.example.android.guesstheword.R
import com.example.android.guesstheword.databinding.GameFragmentBinding
import timber.log.Timber
class GameFragment : Fragment() {
private lateinit var binding: GameFragmentBinding
private lateinit var gameViewModel: GameViewModel
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate view and obtain an instance of the binding class
binding = DataBindingUtil.inflate(
inflater,
R.layout.game_fragment,
container,
false
)
Timber.i("onCreateView GameFragment called")
gameViewModel = ViewModelProvider(this).get(GameViewModel::class.java)
Timber.i("ViewModelProvider is called")
binding.correctButton.setOnClickListener {
gameViewModel.onCorrect()
updateScoreText()
updateWordText()
}
binding.skipButton.setOnClickListener {
gameViewModel.onSkip()
updateScoreText()
updateWordText()
}
updateScoreText()
updateWordText()
return binding.root
}
/**
* Called when the game is finished
*/
fun gameFinished() {
val action = GameFragmentDirections.actionGameToScore(gameViewModel.score)
findNavController(this).navigate(action)
}
/** Methods for updating the UI **/
private fun updateWordText() {
binding.wordText.text = gameViewModel.word
}
private fun updateScoreText() {
binding.scoreText.text = gameViewModel.score.toString()
}
override fun onDestroyView() {
super.onDestroyView()
Timber.i("onDestroyView GameFragment called")
}
}
我的视图模型class
package com.example.android.guesstheword.screens.game
import androidx.lifecycle.ViewModel
import timber.log.Timber
var word = ""
var score = 0
private lateinit var wordList: MutableList<String>
class GameViewModel: ViewModel() {
init {
Timber.i("GameViewModel is created")
resetList()
nextWord()
}
override fun onCleared() {
super.onCleared()
Timber.i("GameViewModel is cleared")
}
/**
* Resets the list of words and randomizes the order
*/
fun resetList() {
wordList = mutableListOf(
"queen",
"hospital",
"basketball",
"cat",
"change",
"snail",
"soup",
"calendar",
"sad",
"desk",
"guitar",
"home",
"railway",
"zebra",
"jelly",
"car",
"crow",
"trade",
"bag",
"roll",
"bubble"
)
wordList.shuffle()
}
/**
* Moves to the next word in the list
*/
private fun nextWord() {
//Select and remove a word from the list
if (wordList.isEmpty()) {
//gameFinished()
} else {
word = wordList.removeAt(0)
}
}
/** Methods for buttons presses **/
fun onSkip() {
score--
nextWord()
}
fun onCorrect() {
score++
nextWord()
}
}
我哪里搞砸了?
您尝试访问的变量不属于同一范围:
var word = ""
var score = 0
private lateinit var wordList: MutableList<String>
class GameViewModel: ViewModel() {
...
您的变量在 ViewModel 外部声明,将它们添加到 class GameViewModel
中以使其成为实例变量:
class GameViewModel: ViewModel() {
var word = ""
var score = 0
...
}