【问题标题】:Android Studio: initializing shared preferences crashing activity launchAndroid Studio:初始化共享首选项崩溃活动启动
【发布时间】:2021-02-16 10:33:15
【问题描述】:

我的 android 应用在从主 Activity 启动 Activity 时崩溃,但只有在我初始化 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)

【问题讨论】:

    标签: android-studio kotlin


    【解决方案1】:

    具体来说是这样的:

    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
    

    它崩溃了,因为你试图在一个空的Context 上调用getPackageName(),这是通过PlayActivity.kt 的第39 行的prefs 对象引起的getPreferences() 调用而发生的。

    这些成员函数在构造 Activity 时被初始化,但此时 Activity 还没有 Context - 这发生在生命周期的后期,并且在 onCreate 时已准备好叫做。所以有些东西必须稍后初始化(lateinit 对这样的事情很有用)

    您的lazy 代表正常工作 - 当它被某些东西访问时,Activity 将拥有它的Context。但是当您初始化editor 时,您将在下一行访问它,因此无论如何它总是在构造中运行,没有必要让它变得懒惰。


    无论如何,您可能不应该持有这样的编辑器引用,尤其是像 KTX Core 这样可以让您一次性编辑、设置和提交的东西:

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

    绝对不要将!! 用于有时绝对可以为空的东西,你最终只会后悔

    【讨论】:

      【解决方案2】:

      在 onCreate() 方法内部之前,您不能调用从 Activity 继承的方法。在那之前,事情还没有建立起来。 所以在 onCreate() 方法中初始化你的对象。

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-09-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-31
          • 1970-01-01
          相关资源
          最近更新 更多