Android studio lateinit属性ApplicationContext尚未初始化
您好,我对编程行业还比较陌生,我的项目有问题。 我有一个简单的计数器,可以计算你看到多少只鸟,然后根据你按下的按钮改变文本视图(显示计数器)的颜色。 我正在使用viewModel和实时数据以及数据绑定来实现这一点,而且效果很好。现在,当我尝试添加共享首选项来存储我的数据,以便它们能够在应用程序关闭后生存下来时。当我尝试使用“userDataProvider”时,我得到了一个我不知道如何修复的错误 //错误 原因:kotlin.UninitializedPropertyAccessException:lateinit属性ApplicationContext尚未初始化 在com.example.lv4_birdsconter.birdsconterApp$Companion.getApplicationContext(birdsconterApp.kt:11) 在com.example.lv4_birdsconter.PrefsManager.setCounter上(PrefsManager.kt:53) 在com.example.lv4_birdsconter.PrefsManager.setBirdCounter(PrefsManager.kt:19)上 在com.example.lv4_birdsconter.birdsconter.onCreate上(birdsconter.kt:52) //鸟计数器Android studio lateinit属性ApplicationContext尚未初始化,android-studio,kotlin,Android Studio,Kotlin,您好,我对编程行业还比较陌生,我的项目有问题。 我有一个简单的计数器,可以计算你看到多少只鸟,然后根据你按下的按钮改变文本视图(显示计数器)的颜色。 我正在使用viewModel和实时数据以及数据绑定来实现这一点,而且效果很好。现在,当我尝试添加共享首选项来存储我的数据,以便它们能够在应用程序关闭后生存下来时。当我尝试使用“userDataProvider”时,我得到了一个我不知道如何修复的错误 //错误 原因:kotlin.UninitializedPropertyAccessExceptio
package com.example.lv4_birdscounter
import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.example.lv4_birdscounter.databinding.ActivityMainBinding
class BirdsCounter : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
lateinit var viewModel: BirdsCounterViewModel
private val userDataProvider: UserDataProvider by lazy { PrefsManager }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel = ViewModelProvider(this).get(BirdsCounterViewModel::class.java)
binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main).apply {
this.setLifecycleOwner(this@BirdsCounter)
this.viewmodel=viewModel
}
viewModel.birdsSeen.observe(this, Observer {
//display new data
binding.tvCounter.text = it.toString()
})
viewModel.birdsColor.observe(this, Observer {
//display new data
binding.tvCounter.setBackgroundColor(Color.parseColor(it))
//Make number more visible by changing the colour of the text
when(it){
viewModel.GREEN -> binding.tvCounter.setTextColor(Color.BLACK)
viewModel.WHITE -> binding.tvCounter.setTextColor(Color.BLACK)
else -> binding.tvCounter.setTextColor(Color.WHITE)
}
})
//Crashes
userDataProvider.birdCounter = 5
setContentView(binding.root)
}
}
//PrefsManager.kt
package com.example.lv4_birdscounter
import android.content.Context
interface UserDataProvider{
var birdCounter: Int
var tvColor: String
}
object PrefsManager: UserDataProvider{
private val PREFS_FILE = "preferences"
private val COUNTER_ID = "counter_id"
private val COLOR_ID = "color_id"
override var birdCounter: Int
get() = getCounter()
set(value) = setCounter(value)
override var tvColor: String
get() = getColor()
set(value) = setColor(value)
//for color
private fun getColor(): String {
return BirdsCounterApp.ApplicationContext.getSharedPreferences(
PREFS_FILE,
Context.MODE_PRIVATE
).getString(COLOR_ID, "#4A6572")?: "#4A6572"
}
private fun setColor(value: String){
BirdsCounterApp.ApplicationContext.getSharedPreferences(
PREFS_FILE,
Context.MODE_PRIVATE)
.edit()
.putString(COLOR_ID, value)
.apply()
}
//for counter
private fun getCounter(): Int {
return BirdsCounterApp.ApplicationContext.getSharedPreferences(
PREFS_FILE,
Context.MODE_PRIVATE
).getInt(COUNTER_ID, 0)?:0
}
private fun setCounter(value: Int){
BirdsCounterApp.ApplicationContext.getSharedPreferences(
PREFS_FILE,
Context.MODE_PRIVATE)
.edit() // dobivamo Editor instancu koja se koristi za izmjenu SharedPreferences-a
.putInt(COUNTER_ID, value)
.apply() // pohranjujemo promjene
}
}
//鸟瞰模型
package com.example.lv4_birdscounter
import android.graphics.Color
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
class BirdsCounterViewModel() : ViewModel() {
val RED = "#D82929"
val BLUE = "#2121E1"
val WHITE = "#FFFFFFFF"
val GREEN = "#2DF62D"
val LIGHT_GRAY = "#4A6572"
private val _birdsSeen: MutableLiveData<Int> = MutableLiveData<Int>(0)
val birdsSeen: LiveData<Int> = _birdsSeen
private val _birdsColor: MutableLiveData<String> = MutableLiveData<String>("#4A6572")
val birdsColor: LiveData<String> = _birdsColor
fun onButtonPressed(color: String){
_birdsSeen.value?.let { _birdsSeen.postValue(it + 1) }
_birdsColor.value?.let { _birdsColor.postValue(color) }
}
fun onResetButtonPressed(){
_birdsSeen.value?.let { _birdsSeen.postValue(0) }
_birdsColor.value?.let { _birdsColor.postValue(LIGHT_GRAY) }
}
}
package com.example.lv4\u鸟计数器
导入android.graphics.Color
导入androidx.lifecycle.LiveData
导入androidx.lifecycle.MutableLiveData
导入androidx.lifecycle.ViewModel
类BirdsCounterViewModel():ViewModel(){
val RED=“#D82929”
val BLUE=“#2121E1”
val WHITE=“#FFFFFFFF”
val GREEN=“#2DF62D”
val浅灰色=“#4A6572”
private val_birdseen:MutableLiveData=MutableLiveData(0)
val birdseen:LiveData=\u birdseen
private val_birdscaolor:MutableLiveData=MutableLiveData(“#4A6572”)
val birdsColor:LiveData=\u birdsColor
按下按钮(颜色:字符串){
_birdseen.value?设{u birdseen.postValue(it+1)}
_birdsColor.value?.let{u birdsColor.postValue(color)}
}
按下重置按钮(){
_birdseen.value?设{u birdseen.postValue(0)}
_birdsColor.value?.let{u birdsColor.postValue(浅灰色)}
}
}
//主活动XML
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="viewmodel"
type="com.example.lv4_birdscounter.BirdsCounterViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/dark_gray"
tools:context=".BirdsCounter">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guide_vertical_center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />
<TextView
android:id="@+id/tvCounter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/tvMargin"
android:background="@color/light_gray"
android:textAlignment="center"
android:textColor="@color/white"
android:textSize="@dimen/tvTextSize"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="@string/tvCounterDefaultValue" />
<Button
android:id="@+id/btnRed"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="@dimen/btnMargin"
android:backgroundTint="@color/red"
android:text="@string/btnRedText"
android:textColor="@color/white"
app:layout_constraintEnd_toStartOf="@id/guide_vertical_center"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvCounter"
app:strokeColor="@color/black"
app:strokeWidth="@dimen/btnStrokeWidth"
android:onClick="@{()->viewmodel.onButtonPressed(viewmodel.RED)}"/>
<Button
android:id="@+id/btnBlue"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="@dimen/btnMargin"
android:backgroundTint="@color/blue"
android:text="@string/btnBlueText"
android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@id/guide_vertical_center"
app:layout_constraintTop_toBottomOf="@id/tvCounter"
app:strokeColor="@color/black"
app:strokeWidth="@dimen/btnStrokeWidth"
android:onClick="@{()->viewmodel.onButtonPressed(viewmodel.BLUE)}"/>
<Button
android:id="@+id/btnWhite"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="@dimen/btnMargin"
android:backgroundTint="@color/white"
android:text="@string/btnWhiteText"
android:textColor="@color/black"
app:layout_constraintEnd_toStartOf="@id/guide_vertical_center"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btnRed"
app:strokeColor="@color/black"
app:strokeWidth="@dimen/btnStrokeWidth"
android:onClick="@{()->viewmodel.onButtonPressed(viewmodel.WHITE)}"/>
<Button
android:id="@+id/btnGreen"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="@dimen/btnMargin"
android:backgroundTint="@color/green"
android:text="@string/btnGreenText"
android:textColor="@color/black"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@id/guide_vertical_center"
app:layout_constraintTop_toBottomOf="@id/btnBlue"
app:strokeColor="@color/black"
app:strokeWidth="@dimen/btnStrokeWidth"
android:onClick="@{()->viewmodel.onButtonPressed(viewmodel.GREEN)}"/>
<Button
android:id="@+id/btnReset"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:backgroundTint="@color/black"
android:text="@string/btnResetText"
android:textColor="@color/white"
app:layout_constraintLeft_toLeftOf="@id/guide_vertical_center"
app:layout_constraintRight_toRightOf="@id/guide_vertical_center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/btnWhite"
android:onClick="@{()->viewmodel.onResetButtonPressed()}"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
您不需要在应用程序类中初始化ApplicationContext。Android将为您提供它。你只需要从你需要的地方访问它。ApplicationContext基本上是一个单例实例,可以通过getApplicationContext()在活动中访问。此上下文与应用程序的生命周期相关联 而不是通过伴随对象访问应用程序上下文。通过构造函数将上下文注入到需要使用的相应文件中,并使用该实例。您还可以使用依赖项注入库(如Dagger)来帮助您注入依赖项 您可以执行类似PrefsManager构造函数(val context:context)的操作
要手动将birds counter活动中的上下文注入PrefsManager,然后使用该上下文保存到SharedReferences感谢您的回答我没有将BirdsCounterApp添加到清单中….--android:name=“.birdsconterApp”--这行代码就是我所需要的
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="viewmodel"
type="com.example.lv4_birdscounter.BirdsCounterViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/dark_gray"
tools:context=".BirdsCounter">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guide_vertical_center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />
<TextView
android:id="@+id/tvCounter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/tvMargin"
android:background="@color/light_gray"
android:textAlignment="center"
android:textColor="@color/white"
android:textSize="@dimen/tvTextSize"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="@string/tvCounterDefaultValue" />
<Button
android:id="@+id/btnRed"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="@dimen/btnMargin"
android:backgroundTint="@color/red"
android:text="@string/btnRedText"
android:textColor="@color/white"
app:layout_constraintEnd_toStartOf="@id/guide_vertical_center"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvCounter"
app:strokeColor="@color/black"
app:strokeWidth="@dimen/btnStrokeWidth"
android:onClick="@{()->viewmodel.onButtonPressed(viewmodel.RED)}"/>
<Button
android:id="@+id/btnBlue"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="@dimen/btnMargin"
android:backgroundTint="@color/blue"
android:text="@string/btnBlueText"
android:textColor="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@id/guide_vertical_center"
app:layout_constraintTop_toBottomOf="@id/tvCounter"
app:strokeColor="@color/black"
app:strokeWidth="@dimen/btnStrokeWidth"
android:onClick="@{()->viewmodel.onButtonPressed(viewmodel.BLUE)}"/>
<Button
android:id="@+id/btnWhite"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="@dimen/btnMargin"
android:backgroundTint="@color/white"
android:text="@string/btnWhiteText"
android:textColor="@color/black"
app:layout_constraintEnd_toStartOf="@id/guide_vertical_center"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btnRed"
app:strokeColor="@color/black"
app:strokeWidth="@dimen/btnStrokeWidth"
android:onClick="@{()->viewmodel.onButtonPressed(viewmodel.WHITE)}"/>
<Button
android:id="@+id/btnGreen"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="@dimen/btnMargin"
android:backgroundTint="@color/green"
android:text="@string/btnGreenText"
android:textColor="@color/black"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@id/guide_vertical_center"
app:layout_constraintTop_toBottomOf="@id/btnBlue"
app:strokeColor="@color/black"
app:strokeWidth="@dimen/btnStrokeWidth"
android:onClick="@{()->viewmodel.onButtonPressed(viewmodel.GREEN)}"/>
<Button
android:id="@+id/btnReset"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:backgroundTint="@color/black"
android:text="@string/btnResetText"
android:textColor="@color/white"
app:layout_constraintLeft_toLeftOf="@id/guide_vertical_center"
app:layout_constraintRight_toRightOf="@id/guide_vertical_center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/btnWhite"
android:onClick="@{()->viewmodel.onResetButtonPressed()}"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>