Java 从Android Room检索双精度值导致NullPointerException
我有一个安卓房间DB和下一个POJOJava 从Android Room检索双精度值导致NullPointerException,java,android,database,nullpointerexception,android-room,Java,Android,Database,Nullpointerexception,Android Room,我有一个安卓房间DB和下一个POJO Entity(tableName = "transactions") public class BoardItem { @PrimaryKey(autoGenerate = true) int itemID; String account; String date; String category; double value: //
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...
要显示,我使用下一个代码:
public class StatisticActivity extends AppCompatActivity {
RoomTransactionsRepository repository;
@Override
protected void onCreate(Bundle savedInstanceState) {
// init code
binding.totalValue.setText (String.valueOf (repository.getAllTransactionInCategory ("Food")));
}
}
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 ()));
});
在DAO或存储库代码中,当我试图显示要从db中提取的双精度值时,我做错了什么导致了NullPointerException?
提前谢谢
更新:VievModel类。在单独的活动中,动态地将数据库中的数据插入到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:我创建了应答中的接口,但将double替换为POJO classvoid onReturned(TransactionStatististicItem项)代码>
步骤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:最后在活动中,我添加了下一个代码:
public class StatisticActivity extends AppCompatActivity {
RoomTransactionsRepository repository;
@Override
protected void onCreate(Bundle savedInstanceState) {
// init code
binding.totalValue.setText (String.valueOf (repository.getAllTransactionInCategory ("Food")));
}
}
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 ()));
});
最后,我能够检索下一个示例数据:“食品”类别中所有事务的总和
为了遵循Google MVVM准则,您不应该从活动访问存储库,因为它被认为是数据库的一个层,不应该由视图处理,而应该由ViewModel
另一个问题是,在不使用侦听器的情况下从数据库返回一个双精度值;由于从数据库获取值需要一些时间,因此getAllTransactionCategory()
不会返回预期值。这可以通过使用侦听器接口来解决,或者返回LiveData
并在活动中观察它
应用它:
因此,建议您通过ViewModel
访问此选项:
Dao:返回一个LiveData
更新:
“这可以通过使用监听器界面来解决”你能详细说明一下吗
要使用侦听器,您需要一个接口,该接口具有一个回调方法,该方法接受您希望从文件室返回的类型,在本例中,它是一个double
public interface TransactionListener {
void onReturned(double count);
}
然后在Room返回如下值时使用此接口的实现:
道:
视图模型:
public class RoomTransactionsViewModel extends AndroidViewModel {
// ...
LiveData<Double> getAllTransactionInCategory (String category){
return mRepo.getAllTransactionInCategory (category);
}
}
public class RoomTransactionsViewModel extends AndroidViewModel {
// ...
void getAllTransactionInCategory (String category, TransactionListener listener){
mRepo.getAllTransactionInCategory (category, listener);
}
}
存储库:
public class RoomTransactionsRepository {
//.....
LiveData<Double> getAllTransactionInCategory (String category){
return mTransactionsDao.getAllTransactionInCategory (category);
}
public class RoomTransactionsRepository {
//.....
void getAllTransactionInCategory (String category, TransactionListener listener){
listener.onReturned(mTransactionsDao.getAllTransactionInCategory (category));
}
活动:
public class StatisticActivity extends AppCompatActivity {
RoomTransactionsRepository repository;
@Override
protected void onCreate(Bundle savedInstanceState) {
// init code
RoomTransactionsViewModel model = new ViewModelProvider(this).get(RoomTransactionsViewModel.class);
model.getAllTransactionInCategory("Food", new TransactionListener() {
@Override
public void onReturned(double count) {
binding.totalValue.setText (String.valueOf (count));
}
});
}
}
能否显示您在何处初始化视图模型RoomTransactionRepository
instances@Zain更新,这是吗?独立活动中涉及的ViewModel允许在RecyclerView中动态插入POJO项目。谢谢!“这可以通过使用监听器界面来解决”你能详细说明一下吗?我还更新了帖子,提供了关于我想要什么的其他信息。@GremlinShX请在回答中查看更新部分。谢谢你,我使用你的回答作为回答我自己问题的基础,但是如果有更改,你可以在问题中查看更新3。还有一件事,您有一个错误:ViewModel类中的void GetAllTransactionCategory不应该使用“return”关键字。
@Query ("SELECT category, SUM (value) as total FROM transactions WHERE category =:transactionCategory GROUP BY category ")
double getAllTransactionInCategory(String transactionCategory);
public class RoomTransactionsViewModel extends AndroidViewModel {
// ...
void getAllTransactionInCategory (String category, TransactionListener listener){
mRepo.getAllTransactionInCategory (category, listener);
}
}
public class RoomTransactionsRepository {
//.....
void getAllTransactionInCategory (String category, TransactionListener listener){
listener.onReturned(mTransactionsDao.getAllTransactionInCategory (category));
}
public class StatisticActivity extends AppCompatActivity {
RoomTransactionsRepository repository;
@Override
protected void onCreate(Bundle savedInstanceState) {
// init code
RoomTransactionsViewModel model = new ViewModelProvider(this).get(RoomTransactionsViewModel.class);
model.getAllTransactionInCategory("Food", new TransactionListener() {
@Override
public void onReturned(double count) {
binding.totalValue.setText (String.valueOf (count));
}
});
}
}