Kotlin房间数据库:如何保存sum查询结果?



我是Kotlin的新手,并试图通过编程一个用于工作时间记录的应用程序来学习它。

我创建了一个房间数据库,它在插入数据时工作良好。在下一步中,我想检索列的和并将该值存储在一个变量中。这就是我被困住的地方。以下是受影响的代码片段:

data class sumPojo(var sumOvertime: Double)

@Dao
interface OvertimeDao {

@Query(value = "SELECT SUM(overtime) as sumOvertime FROM TableOvertime")
fun getSumOvertime(): sumPojo
}

class OvertimeRepository(private val overtimeDao: OvertimeDao) {

val getSumOvertime: sumPojo = overtimeDao.getSumOvertime()

}

class OvertimeViewModel(application: Application): AndroidViewModel(application) {

private val repository : OvertimeRepository
val getSumOvertime : sumPojo

init {
val overtimeDao = OvertimeDatabase.getDatabase(application).overtimeDao()
repository = OvertimeRepository(overtimeDao)           
getSumOvertime = repository.getSumOvertime

}
}

class inputWorktimeFragment : Fragment() {
private lateinit var mOvertimeViewModel : OvertimeViewModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {

val view = inflater.inflate(R.layout.fragment_input_worktime, container, false)
mOvertimeViewModel = ViewModelProvider(this)[OvertimeViewModel::class.java]

val sumOvertime: sumPojo = mOvertimeViewModel.getSumOvertime
return view
}
}

在我收到的错误信息之后。

2022-07-06 16:24:03.067 7338-7338/com.example.workingtimerecorder E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.workingtimerecorder, PID: 7338
java.lang.RuntimeException: Cannot create an instance of class com.example.workingtimerecorder.data.OvertimeViewModel
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:320)
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:278)
at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.kt:128)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:187)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:153)
at com.example.workingtimerecorder.fragments.inputWorktimeFragment.onCreateView(InputWorktimeFragment.kt:55)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:3104)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:524)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261)
at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:113)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1424)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2968)
at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:2879)
at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3129)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:552)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261)
at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:113)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1424)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2968)
at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:2886)
at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:263)
at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:351)
at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:246)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1455)
at android.app.Activity.performStart(Activity.java:8076)
at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3660)
at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221)
at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2210)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7839)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:312)
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:278) 
at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.kt:128) 
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:187) 
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:153) 
at com.example.workingtimerecorder.fragments.inputWorktimeFragment.onCreateView(InputWorktimeFragment.kt:55) 
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:3104) 
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:524) 
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261) 
at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:113) 
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1424) 
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2968) 
at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:2879) 
at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3129) 
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:552) 
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261) 
at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:113) 
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1424) 
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2968) 
at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:2886) 
at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:263) 
at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:351) 
at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:246) 
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1455) 
at android.app.Activity.performStart(Activity.java:8076) 
at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3660) 
at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221) 
at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201) 
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173) 
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2210) 
at android.os.Handler.dispatchMessage(Handler.java:106) 
at android.os.Looper.loopOnce(Looper.java:201) 
at android.os.Looper.loop(Looper.java:288) 
at android.app.ActivityThread.main(ActivityThread.java:7839) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003) 
Caused by: java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
at androidx.room.RoomDatabase.assertNotMainThread(RoomDatabase.java:469)
at androidx.room.RoomDatabase.query(RoomDatabase.java:525)
at androidx.room.util.DBUtil.query(DBUtil.java:86)
2022-07-06 16:24:03.068 7338-7338/com.example.workingtimerecorder E/AndroidRuntime:     at com.example.workingtimerecorder.data.OvertimeDao_Impl.getSumOvertime(OvertimeDao_Impl.java:124)
at com.example.workingtimerecorder.data.OvertimeRepository.<init>(OvertimeRepository.kt:16)
at com.example.workingtimerecorder.data.OvertimeViewModel.<init>(OvertimeViewModel.kt:24)
... 40 more
我将非常感谢你的帮助或任何提示,可以引导我到正确的方向。我在Stackoverflow上读到过几个类似的问题,但是没有一个能帮到我。

由于:java.lang.IllegalStateException:无法在主线程上访问数据库,因为它可能会锁定UI很长一段时间。

我会尝试返回流或实时数据,并使用视图模型作用域来启动co例程。

在dao

//change
fun getSumOvertime(): sumPojo
to
fun getSumOvertime(): LiveData<sumPojo>
//or
suspend fun getSumOvertime(): Flow<sumPojo>

在repo

//livedata
fun getSumPojo():LiveData<sumPojo>{return yourdb.yourdao.getSumovertime}
//flow
suspend fun getSumPojo():Flow<sumPojo>{return yourdb.yourdao.getSumovertime}

视图模型id中的可以访问如下值

// create private and public accessors
private var _sumPojo = MutableLiveData<SumPojo> //use Int as mutable type if you do not have an object to map to
val sumPojo: LiveData<SumPojo> // again if you do not have an object for sumPojo use Int as live data type
get() = _sumPojo
private fun refreshSumPojo()=viewModelScope.launch{return yourRepo.getSumPojo()}
init {_sumPojo.value = refreshSumPojo} 
我将使用数据绑定并将文本视图绑定到公共访问器

在view.xml文件

<TextView
android:text="@{viewModel.sumPojo.toString()}"
" />

最新更新