我正在尝试使用 Kotlin 中的共享首选项加载和保存数据,特别是使用 Android Studio。
我收到此错误消息:
java.lang.NullPointerException:尝试调用虚拟方法 'android.content.SharedPreferences android.content.Context.getSharedPreferences(java.lang.String, int)' 在空对象引用上
指向我的共享首选项的初始化。
class MainActivity : AppCompatActivity(), SensorEventListener {
private val dragonstats by lazy {getSharedPreferences("DRAGON_STATS",Context.MODE_PRIVATE)}
如果我这样写,我会得到同样的错误:
val dragonstats = getSharedPreferences("DRAGON_STATS", Context.MODE_PRIVATE)
我在其他答案中看到这样声明:
SharedPreferences dragonstats
但这在 Kotlin 中是读不出来的。
共享首选项中的 android.com 文件要求以这种方式声明:
val sharedPref = activity?.getSharedPreferences(
getString(R.string.preference_file_key), Context.MODE_PRIVATE)
但这会导致活动出现未解决的参考错误。
如何初始化 SharedPreferences 文件以便在 Kotlin 中存储和检索数据?
编辑: 因此,要使其发挥作用,唯一有效的方法就是放置 ?在一切事情中。
我在 oncreate 之外声明它,这样我就可以在整个过程中使用它:
var dragonstats: SharedPreferences? = null
在 oncreate 中我设置了它:
dragonstats = PreferenceManager.getDefaultSharedPreferences(this)
然后,当我想调用它的任何部分时,我使用 ?:
exerciselevel = dragonstats?.getInt("exerciselevel", 0)!!
我不明白为什么这有效,但其他都不起作用。
我是这样写的。
// in global
private lateinit var pref: SharedPreferences
override fun onCreate(savedInstanceState: Bundle?) {
...
pref = getSharedPreferences("mysharedpref", Context.MODE_PRIVATE)
...
}
主要问题是由于
getSharedPreference()
方法依赖于 Context
的 Activity
引起的。
由于惰性方法是这样声明的:
class MyActivity: Activity(){
private val dragonstats by lazy {getSharedPreferences("DRAGON_STATS",Context.MODE_PRIVATE)}
}
这里懒人无法访问
Context
。
但是,如果我们像这样声明sharedPreferences:
class MyActivity: Activity(){
private lateinit var dragonstats: SharedPreferences
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
dragonstats = getSharedPreferences("DRAGON_STATS",Context.MODE_PRIVATE)
}
}
我们知道
onCreate()
是一个 lifecycle
方法,因此它可以访问 Context
并且可以工作。
注意 - 所有
lifecycle
方法都是如此,如 onResume
、onStart
、onPause
、onDestroy
等,
尝试这样的方法来初始化首选项:
val pref = PreferenceManager.getDefaultSharedPreferences(context)
读取数据:
pref.getString("your_key","default_value")
保存数据:
pref.edit().putString("key","value").apply()
编辑:
如果你想让你的变量全局化,你可以这样做:
lateinit var pref:SharedPreferences
然后在 onCreate() 中:
pref = PreferenceManager.getDefaultSharedPreferences(context)
我刚刚开始学习 Android 和 Kotlin,Jasper Calapini 建议的答案在 Android Studio 4 中对我有用
private lateinit var pref: SharedPreferences
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
pref = getSharedPreferences("myPref", Context.MODE_PRIVATE)
var name: String? = pref.getString("my-string", "hello")
val editor = pref.edit()
editor.putString("my-string", "value is changed")
editor.apply()
println("name = ${name}")
}
正如错误所述,您会得到一个
NullPointerException
,因为 Context
为空。
您当然可以使用它,但请注意关键字 this
是隐式的 :
private val dragonstats by lazy {getSharedPreferences("DRAGON_STATS",Context.MODE_PRIVATE)}
//equivalent to
private val dragonstats by lazy {this.getSharedPreferences("DRAGON_STATS",Context.MODE_PRIVATE)}
[
,]它是应用程序/对象当前状态的上下文。它让新创建的对象了解发生了什么。通常,您调用它是为了获取有关程序的另一部分(活动和包/应用程序)的信息。 查看 SO 的完整答案this
为了不获得 NullPointerException,只有一个条件需要遵守:您必须具有应用程序/活动的上下文。为此,请不要忘记在 OnCreate() 方法中调用
this.setContentView(R.layout.main)
(同样,关键字 this
不是必需的,并且可能是隐式的),这将创建您正在查找的上下文。换句话说,它将“初始化”应用程序上下文this
。
如果您在活动之外需要 SharedPreferences,请查看此答案。
我认为
private val pref by lazy {}
最适合使用(因为val
,而不是var
,并且是在一行代码中初始化的),但请确保在使用this.setContentView(R.layout.main)
之前调用
pref