在 activity 的初始化块中使用 'this' 作为上下文?

Using 'this' as Context in the init block of activity?

我正在使用 kotlin 开发 android 应用程序。

我有一个 DereDatabaseHelper class,它有 init 块,它使用通过 class 参数给出的 context (?)

DereDatabaseHelper是这样的

class DereDatabaseHelper(context: Context) {
    val manifestFile: File
    val fumensDBFile: File
    val fumenFolder: File

    val musicIDToInfo: MutableMap<Int, MusicInfo> = HashMap()
    val fumenIDToMusicID: SparseIntArray = SparseIntArray()

    init {
        val datadir = context.getExternalFilesDir(null).parentFile.parentFile

DereDatabaseHelper class 在这里实例化 SongListActivity 是这样的。

class SongListActivity : AppCompatActivity() {
    var dereDatabaseHelper : DereDatabaseHelper
    init {
        dereDatabaseHelper = DereDatabaseHelper(this)
    }

我认为这段代码是正确的,但这段代码抛出 NullPointerException

java.lang.NullPointerException: Attempt to invoke virtual method

'java.io.File android.content.Context.getExternalFilesDir(java.lang.String)'

on a null object reference at

android.content.ContextWrapper.getExternalFilesDir(ContextWrapper.java:253) at com.kyhsgeekcode.dereinfo.model.DereDatabaseHelper.<init>(DereDatabaseHelper.kt:21) at com.kyhsgeekcode.dereinfo.SongListActivity.<init>(SongListActivity.kt:31)

init 块中执行时 this 是否为空,我应该使用什么初始化样式来解决这个问题?

活动未完全由 constructor 或您的 init 块初始化。

Android系统初始化活动,然后调用onCreate方法。所以你应该做以下事情

override fun onCreate(savedInstanceState: Bundle?) {
 // create instance of DareDatabaseHelper 
}

为什么它不适用于构造函数?

考虑以下代码片段

var myActivity = MyActivity() // This doesn't start MainActivity

// This is how you start an activity
val intent = Intent(context, MyActivity::class.java)
startActivity(intent)

当你启动任何 activity 时,你永远不会实例化 activity class,为什么?

因为这是 android 系统的职责,当您执行 startActivity(intent) android 系统会使用默认 [=12] 实例化您的 activity class =] 然后进行所有初始化(即提供 context)一旦 activity 完全初始化,您的 activity 的 onCreate 方法将被调用,您可以在其中执行您的操作初始化结束。

永远不要使用 Activity 的构造函数来做任何涉及上下文的事情。 Android 使用其唯一的空构造函数(通过反射)实例化 Activity,然后在 调用 之前设置 activity 的各个字段 onCreate() .在 Activity 中执行任何操作的第一个安全入口点位于 onCreate().

您也不能在构造函数中调用 Activity(它本身就是一个上下文)的方法。

您也不能以任何方式使用上下文来设置属性,因为它们会在 onCreate:

之前尝试访问上下文
class MyActivity: AppCompatActivity() {
    val assets: AssetManager = getAssets() // This will cause a crash
}

为了避免必须使您的 属性 可为空,您可以执行以下任一操作,这样您就可以避免在调用 onCreate() 之前实例化您的 class:

class SongListActivity : AppCompatActivity() {
    lateinit var dereDatabaseHelper : DereDatabaseHelper

    override fun onCreate() {
        super.onCreate
        dereDatabaseHelper = DereDatabaseHelper(this)
    }

class SongListActivity : AppCompatActivity() {
    val dereDatabaseHelper by lazy { DereDatabaseHelper(this) }
}