【发布时间】:2021-08-10 01:35:23
【问题描述】:
我有一个带有下一个 POJO 的 android room DB
Entity(tableName = "transactions")
public class BoardItem {
@PrimaryKey(autoGenerate = true)
int itemID;
String account;
String date;
String category;
double value:
//getters and setters
}
对于指定类别的所有值的负载总和,我尝试使用下一个DAO
@Query ("SELECT category, SUM (value) as total FROM transactions WHERE category =:transactionCategory GROUP BY category ")
double getAllTransactionInCategory(String transactionCategory);
以及存储库 android 房间中的下一个代码:
public class RoomTransactionsRepository {
private final RoomTransactionsDAO mTransactionsDao;
private final LiveData<List<TransactionBoardItem>> mAllTransactions;
RoomTransactionsRepository(Application application){
RoomTransactionsDatabase db = RoomTransactionsDatabase.getDatabase(application);
mTransactionsDao = db.transactions_dao();
mAllTransactions = mTransactionsDao.getAllTransactions();
}
LiveData<List<TransactionBoardItem>> getAllTransactions(){
return mAllTransactions;
}
double getAllTransactionInCategory (String category){
return mTransactionsDao.getAllTransactionInCategory (category);
}
//Livedata code...
但是在尝试以其他方式在文本视图中显示数据后,它会抛出下一个 NullPointerException,尽管 db 中有这样的数据(在 Android Studio db 检查器中检查):
2021-05-20 21:38:06.800 6673-6673/com.example.dbexample E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.dbexample, PID: 6673
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.dbexample/com.example.dbexample.transactions.TransactionStatisticActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'double com.example.dbexample.transactions.RoomTransactionsRepository.getAllTransactionInCategory(java.lang.String)' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3792)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3968)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2307)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:246)
at android.app.ActivityThread.main(ActivityThread.java:8506)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1139)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'double com.example.dbexample.transactions.RoomTransactionsRepository.getAllTransactionInCategory(java.lang.String)' on a null object reference
at com.example.dbexample.transactions.TransactionStatisticActivity.onCreate(TransactionStatisticActivity.java:22)
at android.app.Activity.performCreate(Activity.java:8198)
at android.app.Activity.performCreate(Activity.java:8182)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3765)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3968)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2307)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:246)
为了显示,我使用下一个代码:
public class StatisticActivity extends AppCompatActivity {
RoomTransactionsRepository repository;
@Override
protected void onCreate(Bundle savedInstanceState) {
// init code
binding.totalValue.setText (String.valueOf (repository.getAllTransactionInCategory ("Food")));
}
}
当我尝试显示要从数据库中提取的双精度值时,我在 DAO 或存储库代码中做错了什么导致 NullPointerException? 提前致谢!
更新:VievModel 类。它在单独的活动中用于将数据从 DB 动态插入到 RecyclerView 中。
public class RoomTransactionsViewModel extends AndroidViewModel {
private final RoomTransactionsRepository mRepo;
private final LiveData<List<TransactionItem>> mAllTransactions;
public RoomTransactionsViewModel(Application application){
super(application);
mRepo = new RoomTransactionsRepository(application);
mAllTransactions = mRepo.getAllTransactions();
}
LiveData<List<TransactionBoardItem>> getAllTransactions(){
return mAllTransactions;
}
public void insert(TransactionItem item){mRepo.insertTransaction(item);}
public void deleteAll(){mRepo.deleteAllTransactions();}
}
更新 2:我修改了答案,但使用了稍微不同的方法来解决我的问题。
第 1 步:我为要提取的行创建 POJO:
public class TransactionStatisticItem {
//`@ColumnInfo(name = "")` should equal to name of row in your DB
@ColumnInfo(name = "value")
double transactionValue;//+
//getters
public TransactionStatisticItem(double transactionValue, String transactionCategory) {
this.transactionValue = transactionValue;
this.transactionCategory = transactionCategory;
}
@ColumnInfo(name = "category")
String transactionCategory;//+
}
第 2 步:我按照答案创建了界面,但将 double 替换为 POJO 类 void onReturned(TransactionStatisticItem item);
第 3 步:根据答案更新存储库代码,但有更改:
//To retrieve data asynchronous from DB you can use : ExecutorService (java) / Coroutines (kotlin) or AsyncTask (deprecated in API level 30)
public static final ExecutorService singleThreadExecutor =
Executors.newSingleThreadExecutor();
void getAllTransactionInCategory (String category, TransactionStatisticListener listener){
singleThreadExecutor.execute(() -> listener.onReturned(mTransactionsDao.getAllTransactionInCategory (category)));
}
第 4 步:在 ViewModel 中,我添加下一行
void getAllTransactionInCategory (String category, TransactionStatisticListener listener){
mRepo.getAllTransactionInCategory (category, listener);
}
第 5 步:最后在 Activity 中添加下一个代码:
RoomTransactionsViewModel model = new ViewModelProvider (this).get(RoomTransactionsViewModel.class);
model.getAllTransactionInCategory("Food", item -> {
binding.totalValue.setText (String.valueOf (item.getTransactionValue ()));
binding.category.setText (String.valueOf (item.getTransactionCategory ()));
});
最后,我能够检索到下一个示例数据:“食品”类别中所有交易的总和。
【问题讨论】:
-
你能说明你在哪里初始化
RoomTransactionsRepository和 ViewModel 实例 -
@Zain 更新了,是这个吗? ViewModel 涉及单独的活动,以提供在 RecyclerView 中动态插入 POJO 项的可能性。
标签: java android database nullpointerexception android-room