使用Room查询时没有记录怎么办?

What happens if no records exists when I use Room to query?

我在我的 Android Studio 应用程序中使用 Room,当没有记录可供查询时,代码 A 会崩溃

使用Code B查询Room时没有记录怎么办?

@Dao
interface  RecordDao {

   // Code A
   @Query("SELECT * FROM record_table where id=:id")
   fun getByID(id:Int): Flow<RecordEntity>


   // Code B
   @Query("SELECT * FROM record_table")
   fun getAll(): Flow<List<RecordEntity>>

}

如果您查看 room 为 RecordDao_Impl class RecordDao 实现生成的代码,您会注意到很多事情:

  1. 当 table 中不存在匹配记录时,getById 函数代码 return 为空,并且由于您的 'Code A' 函数 return 类型不为空,kotlin 抛出第一个函数的 NullPointerException。
  2. getAll 函数代码 return 是一个带有 ArrayList 的 Flow 对象,如果它找到任何记录,则会将它们添加到列表中,否则它只会将空的 ArrayList 发送到 Flow 对象,因此,您无论 room 是否找到匹配的记录,都会得到一个包含列表的流对象,因此不会抛出异常。

如果您在此处查看为这两个函数生成的代码,您可以更深入地理解这一点:

@Override
public Flow<RecordEntity> getByID(final int id) {
    final String _sql = "SELECT * FROM record_table where id=?";
    final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 1);
    int _argIndex = 1;
    _statement.bindLong(_argIndex, id);
    return CoroutinesRoom.createFlow(__db, false, new String[]{"record_table"}, new Callable<RecordEntity>() {
        @Override
        public RecordEntity call() throws Exception {
            final Cursor _cursor = DBUtil.query(__db, _statement, false, null);
            try {
                final int _cursorIndexOfId = CursorUtil.getColumnIndexOrThrow(_cursor, "id");
                final RecordEntity _result;
                if (_cursor.moveToFirst()) {
                    final int _tmpId;
                    _tmpId = _cursor.getInt(_cursorIndexOfId);
                    _result = new RecordEntity(_tmpId);
                } else {
                    _result = null;
                }
                return _result;
            } finally {
                _cursor.close();
            }
        }

        @Override
        protected void finalize() {
            _statement.release();
        }
    });
}

@Override
public Flow<List<RecordEntity>> getAll() {
    final String _sql = "SELECT * FROM record_table";
    final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 0);
    return CoroutinesRoom.createFlow(__db, false, new String[]{"record_table"}, new Callable<List<RecordEntity>>() {
        @Override
        public List<RecordEntity> call() throws Exception {
            final Cursor _cursor = DBUtil.query(__db, _statement, false, null);
            try {
                final int _cursorIndexOfId = CursorUtil.getColumnIndexOrThrow(_cursor, "id");
                final List<RecordEntity> _result = new ArrayList<RecordEntity>(_cursor.getCount());
                while (_cursor.moveToNext()) {
                    final RecordEntity _item;
                    final int _tmpId;
                    _tmpId = _cursor.getInt(_cursorIndexOfId);
                    _item = new RecordEntity(_tmpId);
                    _result.add(_item);
                }
                return _result;
            } finally {
                _cursor.close();
            }
        }

        @Override
        protected void finalize() {
            _statement.release();
        }
    });
}