RuntimeException:首选项尚未初始化

RuntimeException: preferences has not been initialised

我搜索了很多类似的 SharedPreferences 问题,但无法应用于我的项目。 这是一个 RuntimeException,需要初始化 SharedPreferences lateinit 变量。

错误信息:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.me.tabuild3/com.me.tabuild3.Tutorial}: kotlin.UninitializedPropertyAccessException: lateinit property mPref has not been initialized

(...)

Caused by: kotlin.UninitializedPropertyAccessException: lateinit property mPreferences has not been initialized
    at com.me.tabuild3.Z3Preferences.<init>(Z3Preferences.kt:15)
    at com.me.tabuild3.Tutorial.onCreate(Tutorial.kt:15)

这是Tutorial.kt,它触发了错误:

class Tutorial : AppCompatActivity() {
   val binding by lazy {
       B00TutorialBinding.inflate(layoutInflater)
   }
   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContentView(R.layout.b00_tutorial)
       
       val fragmentList = listOf(Z0A(), Z1B(), Z3Preferences()) // the 15th line is here
       val adapter = Z99FragmentAdapter(this)
       adapter.fragmentList = fragmentList

       binding.tutorialPager.adapter = adapter
       binding.tutorialPager.currentItem = 1
   }
}

这个activity加载了三个片段,第三个,Z3Preferences(),编辑SharedPreferences来修改东西(至少我是这么打算的)。

这是 Z3Preferences,其中包含实际(?)错误:

class Z3Preferences : Fragment() {
   lateinit var binding: F04PrefBinding
   private lateinit var mPref: SharedPreferences // seems this thing has to be initialised
   val preferencesEditor: SharedPreferences.Editor = mPref.edit() // same error message for this line when the upper solved(?)

   override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
       binding = F04PrefBinding.inflate(inflater, container, false)
       return binding.root
   }

   override fun onResume() {
       super.onResume()
       binding.radioGroupTextSize.setOnCheckedChangeListener { group, checkedId ->
        when (checkedId) {
            R.id.textSize_RB1 -> preferencesEditor.putInt("TXTSZ", 12)
            R.id.textSize_RB2 -> preferencesEditor.putInt("TXTSZ", 14)
            R.id.textSize_RB3 -> preferencesEditor.putInt("TXTSZ", 16)
            R.id.textSize_RB4 -> preferencesEditor.putInt("TXTSZ", 18)
            R.id.textSize_RB5 -> preferencesEditor.putInt("TXTSZ", 20)
        }
    }
    binding.radioGroupTextSpeed.setOnCheckedChangeListener { group, checkedId ->
        when (checkedId) {
               R.id.textSpd_RB1 -> {
                   preferencesEditor.putInt("TXTSP", 160)
                   preferencesEditor.putBoolean("TXTAN", true)
               }
               R.id.textSpd_RB2 -> {
                   preferencesEditor.putInt("TXTSP", 120)
                   preferencesEditor.putBoolean("TXTAN", true)
               }
               R.id.textSpd_RB3 -> {
                   preferencesEditor.putInt("TXTSP", 80)
                   preferencesEditor.putBoolean("TXTAN", true)
               }
               R.id.textSpd_RB4 -> {
                   preferencesEditor.putInt("TXTSP", 40)
                   preferencesEditor.putBoolean("TXTAN", true)
               }
               R.id.textSpd_RB5 -> {
                   preferencesEditor.putInt("TXTSP", 40)
                   preferencesEditor.putBoolean("TXTAN", false)
               }
           }
       }
   }

   override fun onPause() {
       super.onPause()
       preferencesEditor.apply()
   }
}

所以..我该如何初始化 lateinit var mPref?在这一点上我完全迷路了,类似的问题有不同的应用程序构造,我无法理解。

您需要上下文来初始化 sharedPreferences。 你可以这样做:

mPref = this.activity!!.getSharedPreferences("pref", Context.MODE_PRIVATE)

我会在片段的 onCreate 方法中执行此操作。

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mPref = this.activity!!.getSharedPreferences("pref",Context.MODE_PRIVATE)
        //other initializations ...
    }

So.. How do I initialise the lateinit var mPref?

您将其设置为某个有效值,通常尽早设置。在 Android 上,这通常意味着在 onCreateonCreateView 上这样做。但至少在任何尝试访问它之前。您可以在 onCreateView:

中执行此操作
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
   mPref = // get preferences in your prefered way
   binding = F04PrefBinding.inflate(inflater, container, false)
   return binding.root
}

it shoots the same error for the next line(I marked on the code in the post): "lateinit property mPref has not been initialized", but at the next line! How do I do this?

您试图在声明后立即使用未初始化的 lateinit 变量:

private lateinit var mPref: SharedPreferences // Declared but not initialized
val preferencesEditor: SharedPreferences.Editor = mPref.edit() // Immediately attemps to use mPref which is not initialized (during constructor call)

你不需要像那样立即初始化编辑器。

您可以将其设置为 属性,因此它仅在访问时尝试访问 mPref,而在构造函数调用期间 不尝试 ,这假定它是有效的您尝试访问编辑器的时间:

val preferencesEditor: SharedPreferences.Editor get() = mPref.edit()

或者,您可以将编辑器本身设为 lateinit 属性 并稍后对其进行初始化:

lateinit var preferencesEditor: SharedPreferences.Editor

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
   mPref = // get preferences in your prefered way
   preferencesEditor = mPref.edit()
   binding = F04PrefBinding.inflate(inflater, container, false)
   return binding.root
}

请查看文档以了解 lateinit and kotlin constructors 的工作原理。