我在 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中的值,但我想在这个文件中使用它,它返回空指针异常。我可以改变什么来让它发挥作用?谢谢。
您不能只调用 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
首先,您不应该将数据库传递给可组合项。标准架构模式是为您的应用程序创建一个存储库,并让 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,因为它是最容易学习的。