如何从 kotlin Android 中的其他文件访问 MainActivity 中的值

问题描述 投票:0回答:2

我在 MainActivity 中创建了一个数据库,我需要另一个类中的数据库实例,但它给出了此错误

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

这是主要活动

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 -> this is line where the above error is showing
    //  val databaseItems by database.menuItemDao().getAll().observeAsState(emptyList())

这行

val databaseItems by database.menuItemDao().getAll().observeAsState(emptyList())
返回MainActivity中的值,但我想在这个文件中使用它,它返回空指针异常。我可以改变什么来让它发挥作用?谢谢。

android kotlin nullpointerexception
2个回答
0
投票

您不能只调用 MainActivity 构造函数,您尝试访问数据库的方式是错误的。至少你应该使用一些 ViewModel 来存储你的数据库类。但在您的情况下,您可以将数据库实例放入某个对象中,如下所示:

object DatabaseStorage {

    var databaseInstance: YourDatabaseClass? = null
}

class MainActivity {

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

   override fun onCreate(...) {

        DatabaseStorage.databaseInstance = database
    }
}

// and in your fun
@Composable
fun Piece() {
    val databaseInstance = DatabaseStorage.databaseInstance 
}

但是这种方法确实是一个糟糕的解决方案,你应该使用一些 DI 库,并且只在数据层直接使用你的数据库。您可以阅读这篇文章以获得更好的解决方案https://proandroiddev.com/news-android-app-607f9dc6a3d1


0
投票

首先,您不应该将数据库传递给可组合项。标准架构模式是为您的应用程序创建一个存储库,并让 viewModel 完成与数据库的所有连接,然后您可以从中返回一个流。

类似:

class myDatabase {
     lateinit var dataBase: AppDatabase
     val dao = MyDatabaseDao()

     fun build(context: Context) {
     database = Room.databaseBuilder(context,AppDatabase::class.java,"database").build()
     }
}

class myApplication: Application { 
    override onCreate { 
        MyDatabase().build()
}

interface MyDatabaseRepo { 
    fun grabDataFromDatabase()
}

class MyDatabaseRepoImpl: MyDatabaseRepo { 
    val myDao = MyDatabase().dao

    override fun grabDataFromDatabase() { 
        myDao.doSomething()
    }
                 
}


class myViewModel(databaseRepo: MyDatabaseRepo): ViewModel() { 
    
    val myStateFlow = MutableStateFlow(listOf<Int>()) 

    fun grabData() {
       myStateFlow.update { databaseRepo.grabSomthingFromDatabase()}
    }

}

@Composable
fun Piece(viewModel:MyViewModel) { 
     val data = viewModel.myStateFlow.collectAsState()

}

但正如 Vinny 所说,您可能应该使用一些依赖项注入来使其真正干净。这会给你很多自由。我推荐 koin,因为它是最容易学习的。

© www.soinside.com 2019 - 2024. All rights reserved.