提问人:M Baig 提问时间:10/5/2023 更新时间:10/5/2023 访问量:38
如何从 kotlin Android 中的其他文件访问 MainActivity 中的值
how to access the value in MainActivity from other file in kotlin Android
问:
我已经在MainActivity中创建了一个数据库,并且需要另一个类中的数据库实例,但是它给出了此错误
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 -> this is line where the above error is showing
// val databaseItems by database.menuItemDao().getAll().observeAsState(emptyList())
此行返回 MainActivity 中的值,但我想在此文件中使用它,它返回 null 指针异常。我可以更改什么才能使其正常工作?谢谢。val databaseItems by database.menuItemDao().getAll().observeAsState(emptyList())
答:
0赞
Vinny_Vl
10/5/2023
#1
您不能只调用 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赞
Kristy Welsh
10/5/2023
#2
首先,你不应该将数据库传递给你的可组合项。标准架构模式是为应用创建一个存储库,并让 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,因为它是最容易学习的。
评论