You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin Android:跨文件访问MainActivity数据库实例及空指针解决

问题描述

在MainActivity中创建了Room数据库实例,在Compose组件Piece.kt中使用时触发空指针异常:

java.lang.NullPointerException: Attempt to invoke virtual method
'android.content.Context android.content.Context.getApplicationContext()' on a null object reference

MainActivity代码:

class MainActivity : ComponentActivity() {
    
    val database by lazy {
        Room.databaseBuilder(applicationContext,AppDatabase::class.java,"database").build()
    }

    @SuppressLint("CoroutineCreationDuringComposition")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            
        val databaseMenuItems by database.menuItemDao().getAll().observeAsState(emptyList())
            //
    }
   }

Piece.kt中的错误用法:

@Composable
fun Piece(){
 
    val mainActivity = MainActivity()
    val database = mainActivity.database // 此处触发上述错误
    //  val databaseItems by database.menuItemDao().getAll().observeAsState(emptyList())
}

问题原因

手动new MainActivity()创建的实例并非系统托管的Activity实例,未经过完整初始化流程,applicationContext为空,调用database这个lazy属性时自然触发空指针。

解决方案

方案1:参数传递数据库实例(简单直接)

在MainActivity中调用Piece组件时,直接传入已初始化的数据库实例:

修改MainActivity的setContent代码:

setContent {
    val databaseMenuItems by database.menuItemDao().getAll().observeAsState(emptyList())
    Piece(database = database) // 传入数据库实例
}

修改Piece.kt:

@Composable
fun Piece(database: AppDatabase){
    val databaseItems by database.menuItemDao().getAll().observeAsState(emptyList())
    // 后续使用databaseItems进行UI渲染即可
}

方案2:依赖注入(推荐复杂项目使用)

使用Hilt等依赖注入框架管理Database实例,避免组件间耦合:

  1. 配置Hilt后,通过@Provides方法在Module中提供Database实例
  2. 在MainActivity中注入Database
  3. 在Compose组件中结合ViewModel或直接注入Database实例(推荐通过ViewModel间接访问,符合MVVM架构)

方案3:通过LocalContext获取Activity实例(不推荐,耦合性高)

如果不想传参,可通过LocalContext获取当前Activity实例,但会强耦合组件与MainActivity:

@Composable
fun Piece(){
    val context = LocalContext.current
    val mainActivity = context as? MainActivity ?: return
    val database = mainActivity.database
    val databaseItems by database.menuItemDao().getAll().observeAsState(emptyList())
}

内容的提问来源于stack exchange,提问作者M Baig

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 12:32:36