Android Studio:初始化共享首选项会导致活动启动崩溃

时间:2020-11-03 17:59:04

标签: android-studio kotlin

从主活动启动活动时,我的android应用程序崩溃,但仅当我初始化SharedPreferences对象时。

在主要活动中:

package my.investing.investingtestapp

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        btnPlay.setOnClickListener {
            // Handler code here.
            val I = Intent(this, PlayActivity::class.java)
            startActivity(I);
        }
    }
}

播放活动中:

package my.company.example

import android.content.Context
import android.content.SharedPreferences
import android.content.SharedPreferences.Editor
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity

class PlayActivity : AppCompatActivity() {

    val prefs: SharedPreferences? by lazy { this.getPreferences(Context.MODE_PRIVATE) }
    val editor: Editor = prefs!!.edit()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_play2)
    }
}

对于以下情况也是如此:

val prefs = this.getPreferences(Context.MODE_PRIVATE)

错误: java.lang.RuntimeException:无法实例化活动ComponentInfo {my.company.example / my.company.example.PlayActivity}:java.lang.NullPointerException:尝试调用虚拟方法'java.lang.String android.content.Context。空对象引用上的getPackageName()' 在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3365) 在android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601) 在android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85) 在android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 在android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:2066) 在android.os.Handler.dispatchMessage(Handler.java:106) 在android.os.Looper.loop(Looper.java:223) 在android.app.ActivityThread.main(ActivityThread.java:7656) 在java.lang.reflect.Method.invoke(本机方法) 在com.android.internal.os.RuntimeInit $ MethodAndArgsCaller.run(RuntimeInit.java:592) 在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) 原因:java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法'java.lang.String android.content.Context.getPackageName()' 在android.content.ContextWrapper.getPackageName(ContextWrapper.java:149) 在android.app.Activity.getLocalClassName(Activity.java:6738) 在android.app.Activity.getPreferences(Activity.java:6782) 在my.company.example.PlayActivity $ prefs $ 2.invoke(PlayActivity.kt:39) 在my.company.example.PlayActivity $ prefs $ 2.invoke(PlayActivity.kt:37) 在kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74) 在my.company.example.PlayActivity.getPrefs(未知来源:2) 在my.company.example.PlayActivity。(PlayActivity.kt:40) 在java.lang.Class.newInstance(本机方法) 在android.app.AppComponentFactory.instantiateActivity(AppComponentFactory.java:95) 在androidx.core.app.CoreComponentFactory.instantiateActivity(CoreComponentFactory.java:45) 在android.app.Instrumentation.newActivity(Instrumentation.java:1253) 在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3353) 在android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601) 在android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85) 在android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 在android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:2066) 在android.os.Handler.dispatchMessage(Handler.java:106) 在android.os.Looper.loop(Looper.java:223) 在android.app.ActivityThread.main(ActivityThread.java:7656) 在java.lang.reflect.Method.invoke(本机方法) 在com.android.internal.os.RuntimeInit $ MethodAndArgsCaller.run(RuntimeInit.java:592) com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

3 个答案:

答案 0 :(得分:2)

只有在onCreate()方法内部,才能调用从Activity继承的方法。在此之前,还没有建立任何东西。 因此,请使用onCreate()方法初始化对象。

答案 1 :(得分:2)

具体来说就是这个

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method
'java.lang.String android.content.Context.getPackageName()' on a null object
reference at
android.content.ContextWrapper.getPackageName(ContextWrapper.java:149) at
android.app.Activity.getLocalClassName(Activity.java:6738) at
android.app.Activity.getPreferences(Activity.java:6782) at
my.company.example.PlayActivity$prefs$2.invoke(PlayActivity.kt:39) at

它崩溃是因为您尝试在空getPackageName()上调用Context,这是由于getPreferences()对象在第39行的第prefs个对象引起的PlayActivity.kt

这些成员函数是在构造Activity时初始化的,但是此时Activity还没有Context-在生命周期的后期发生,并且已经准备就绪到onCreate被调用时。因此,有些事情必须稍后进行初始化(lateinit对于此类事情很有用)

您的lazy代表正常工作-到某人对其进行访问时,Activity将拥有其Context。但是,在初始化editor时,您将在下一行访问它,因此无论如何它始终在构造中运行,并且没有任何意义使其变得懒惰。


无论如何,您可能都不应该拥有这样的编辑器参考,尤其是对于KTX Core这样的东西,它使您可以一次完成所有编辑,设置和提交操作:

sharedPreferences.edit { putBoolean("key", value) 

在某些绝对可以为null的东西上绝对不要使用!!,您只会后悔

答案 2 :(得分:0)

尝试在setcontentview之后将editor = prefs?.edit()放入oncreate中。 顺便说一句!不安全,因为它可能会抛出KotlinNullPointerException

相关问题