道室数据库。如何对所有金额求和并将其作为 TextView 查看?
Dao Room database. How to SUM all the amounts and view it as a TextView?
我正在创建一个简单的费用跟踪器。
我可以将项目添加到数据库并在 recyclerview 中查看它们。
但是当我尝试对列中的所有值求和时,它只是 return 0 而不是所有值的总和。
首先,这是我要汇总的值的列。
@ColumnInfo(name = "amount")
public int Amount;`
这是 Dao 查询:
@Query("SELECT SUM(amount) as total FROM Item")
public int getTotalSum();
项目是我的实体的名称class
我是这样使用 AsyncTask 的:
private static class GetTotalAsyncTask extends AsyncTask<Integer, Void,
Void>{
private DaoInterface asyncTaskDao;
private int sumValue;
private GetTotalAsyncTask(DaoInterface noteDao) {
this.asyncTaskDao = noteDao;
}
@Override
protected Void doInBackground(Integer... params) {
sumValue = asyncTaskDao.getTotalSum();
return null;
}
}
public int sumAllItems(){
GetTotalAsyncTask task = new GetTotalAsyncTask(dao);
task.execute();
String tempSum = task.sumValue;
return tempSum;
}
然后在我的主视图模型中创建方法
public int sumAllItems() {
return repository.sumAllItems();
}
然后我在 Activity class.
中调用
我在 onCreate 中调用这个方法是这样的:
int myTotaltext = mainViewModel.sumAllItems();
totalAmount.setText(myTotaltext + " kr");
我记录了tempSum的值,调用onCreate时为0。
有谁知道可能是什么问题?我的dao查询有什么问题吗?
编辑 1:
我更改了它,所以我直接访问 getTotalSum,而不是使用 Async。
在我的 Activity 中,我观察到这样的值:
final Observer<Integer> sumObserver = new Observer<Integer>() {
@Override
public void onChanged(Integer totalSum) {
totalAmount.setText(totalSum);
}
};
mainViewModel.sumAllItems().observe(this, sumObserver);
但它告诉我:尝试在空对象引用 上调用虚拟方法'int java.lang.Integer.intValue()'。
我不明白 sumAllItems 为何为空?
编辑 2.
EDIT1 上的错误输出完整错误
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.pf, PID: 26498
java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.Integer.intValue()' on a null object reference
at com.example.pf.Activities.MyBudgetActivity.onChanged(MyBudgetActivity.java:100)
at com.example.pf.Activities.MyBudgetActivity.onChanged(MyBudgetActivity.java:97)
at androidx.lifecycle.LiveData.considerNotify(LiveData.java:133)
at androidx.lifecycle.LiveData.dispatchingValue(LiveData.java:151)
at androidx.lifecycle.LiveData.setValue(LiveData.java:309)
at androidx.lifecycle.LiveData.run(LiveData.java:93)
at android.os.Handler.handleCallback(Handler.java:888)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:8178)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)
编辑 3 - 解决方案
在 Stephane Piedjou 的帮助下,解决方案是创建一个观察者。
Edit 1的问题是我没有直接从dao观察数据。
我改变了这个并且它起作用了。
mainViewModel.repository.dao.getTotalSum().observe(this, new Observer<Integer>() {
@Override
public void onChanged(Integer integer) {
totalAmount.setText(integer + " kr");
}
});
您的查询是 运行 异步查询。 task.execute() 将 运行 另一个线程上的操作,当您分配 sumValue (task.sumValue) 时它仍然为空,因为另一个线程尚未完成其操作。
解决方案在您的 dao 中,而不是 returning int 您的 return 实时数据
public LiveData<Integer> getTotalSum();
在您的存储库中,您直接调用 getTotaSum() 而不是调用 AsyncTask
public LiveData<Integer> sumAllItems(){
return dao.getTotalSum();
}
你可以在你的 activity 中用类似的东西观察结果。
viewModel.getTotalSum().observe(getViewLifecycleOwner(), (int sum)->{
// totalAmount.setText(sum + " kr");
});
有关实时数据的详细信息,请参阅 here
sumAllItems()
方法启动一个 AsyncTask
来执行异步操作。但随后它会尝试在下一行读取此操作的值(当它尚未准备好时)。在 AsyncTask
中重写 onPostExecute()
,这是一个回调,指示 AsyncTask
已完成。通过该方法,您将能够获取结果。
我正在创建一个简单的费用跟踪器。 我可以将项目添加到数据库并在 recyclerview 中查看它们。 但是当我尝试对列中的所有值求和时,它只是 return 0 而不是所有值的总和。 首先,这是我要汇总的值的列。
@ColumnInfo(name = "amount")
public int Amount;`
这是 Dao 查询:
@Query("SELECT SUM(amount) as total FROM Item")
public int getTotalSum();
项目是我的实体的名称class
我是这样使用 AsyncTask 的:
private static class GetTotalAsyncTask extends AsyncTask<Integer, Void,
Void>{
private DaoInterface asyncTaskDao;
private int sumValue;
private GetTotalAsyncTask(DaoInterface noteDao) {
this.asyncTaskDao = noteDao;
}
@Override
protected Void doInBackground(Integer... params) {
sumValue = asyncTaskDao.getTotalSum();
return null;
}
}
public int sumAllItems(){
GetTotalAsyncTask task = new GetTotalAsyncTask(dao);
task.execute();
String tempSum = task.sumValue;
return tempSum;
}
然后在我的主视图模型中创建方法
public int sumAllItems() {
return repository.sumAllItems();
}
然后我在 Activity class.
中调用我在 onCreate 中调用这个方法是这样的:
int myTotaltext = mainViewModel.sumAllItems();
totalAmount.setText(myTotaltext + " kr");
我记录了tempSum的值,调用onCreate时为0。
有谁知道可能是什么问题?我的dao查询有什么问题吗?
编辑 1:
我更改了它,所以我直接访问 getTotalSum,而不是使用 Async。 在我的 Activity 中,我观察到这样的值:
final Observer<Integer> sumObserver = new Observer<Integer>() {
@Override
public void onChanged(Integer totalSum) {
totalAmount.setText(totalSum);
}
};
mainViewModel.sumAllItems().observe(this, sumObserver);
但它告诉我:尝试在空对象引用 上调用虚拟方法'int java.lang.Integer.intValue()'。 我不明白 sumAllItems 为何为空?
编辑 2.
EDIT1 上的错误输出完整错误
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.pf, PID: 26498
java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.Integer.intValue()' on a null object reference
at com.example.pf.Activities.MyBudgetActivity.onChanged(MyBudgetActivity.java:100)
at com.example.pf.Activities.MyBudgetActivity.onChanged(MyBudgetActivity.java:97)
at androidx.lifecycle.LiveData.considerNotify(LiveData.java:133)
at androidx.lifecycle.LiveData.dispatchingValue(LiveData.java:151)
at androidx.lifecycle.LiveData.setValue(LiveData.java:309)
at androidx.lifecycle.LiveData.run(LiveData.java:93)
at android.os.Handler.handleCallback(Handler.java:888)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:8178)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)
编辑 3 - 解决方案
在 Stephane Piedjou 的帮助下,解决方案是创建一个观察者。 Edit 1的问题是我没有直接从dao观察数据。
我改变了这个并且它起作用了。
mainViewModel.repository.dao.getTotalSum().observe(this, new Observer<Integer>() {
@Override
public void onChanged(Integer integer) {
totalAmount.setText(integer + " kr");
}
});
您的查询是 运行 异步查询。 task.execute() 将 运行 另一个线程上的操作,当您分配 sumValue (task.sumValue) 时它仍然为空,因为另一个线程尚未完成其操作。 解决方案在您的 dao 中,而不是 returning int 您的 return 实时数据
public LiveData<Integer> getTotalSum();
在您的存储库中,您直接调用 getTotaSum() 而不是调用 AsyncTask
public LiveData<Integer> sumAllItems(){
return dao.getTotalSum();
}
你可以在你的 activity 中用类似的东西观察结果。
viewModel.getTotalSum().observe(getViewLifecycleOwner(), (int sum)->{
// totalAmount.setText(sum + " kr");
});
有关实时数据的详细信息,请参阅 here
sumAllItems()
方法启动一个 AsyncTask
来执行异步操作。但随后它会尝试在下一行读取此操作的值(当它尚未准备好时)。在 AsyncTask
中重写 onPostExecute()
,这是一个回调,指示 AsyncTask
已完成。通过该方法,您将能够获取结果。