You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Room KSP可空性处理异常问题咨询

问题描述

我的Android应用中有如下Room DAO函数:

@RawQuery
@Transaction
abstract suspend fun queryOneOrNone(query: SupportSQLiteQuery): TEntity?

kapt生成的Java代码如下:

@Override
public Object queryOneOrNone(final SupportSQLiteQuery query,
    final Continuation<? super MyEntity> $completion) {
  final CancellationSignal _cancellationSignal = DBUtil.createCancellationSignal();
  return CoroutinesRoom.execute(__db, true, _cancellationSignal, new Callable<MyEntity>() {
    @Override
    @Nullable
    public MyEntity call() throws Exception {
      __db.beginTransaction();
      try {
        final Cursor _cursor = DBUtil.query(__db, query, false, null);
        try {
          final MyEntity _result;
          if (_cursor.moveToFirst()) {
            _result = __entityCursorConverter_persistenceStorageMyEntity(_cursor);
          } else {
            _result = null;
          }
          __db.setTransactionSuccessful();
          return _result;
        } finally {
          _cursor.close();
        }
      } finally {
        __db.endTransaction();
      }
    }
  }, $completion);
}

而KSP生成的代码如下:

public override suspend fun queryOneOrNone(query: SupportSQLiteQuery):
    MyEntity? {
  val _cancellationSignal: CancellationSignal? = createCancellationSignal()
  return execute(__db, true, _cancellationSignal, object :
      Callable<MyEntity?> {
    public override fun call(): MyEntity? {
      __db.beginTransaction()
      try {
        val _cursor: Cursor = query(__db, query, false, null)
        try {
          val _result: MyEntity
          if (_cursor.moveToFirst()) {
            _result =
                __entityCursorConverter_persistenceStorageMyEntity(_cursor)
          } else {
            error("The query result was empty, but expected a single row to return a NON-NULL object of type <MyEntity>.")
          }
          __db.setTransactionSuccessful()
          return _result
        } finally {
          _cursor.close()
        }
      } finally {
        __db.endTransaction()
      }
    }
  })
}

应用运行时抛出错误:

"The query result was empty, but expected a single row to return a NON-NULL object of type <MyEntity>."

目前我可以通过在Gradle中添加如下配置缓解问题,但更希望保留KSP生成Kotlin代码的功能:

ksp {
    arg("room.generateKotlin", "false")
}

请问这是KSP的问题,还是我的应用代码存在错误?


结论与解决方案

这是Room KSP处理器的bug,和你的应用代码无关。

从代码对比可以明确看出:

  • kapt生成的代码正确适配了可空返回类型TEntity?:当查询无结果时返回null
  • KSP生成的代码存在逻辑错误:尽管返回类型标注为可空的MyEntity?,但在查询无结果时却调用error()抛出异常,而非返回null

解决办法:

  1. 升级Room版本:该bug在Room 2.5.0及后续版本中已被修复,建议直接升级Room依赖到对应版本
  2. 临时替代方案:如果暂时无法升级,可继续使用你提到的Gradle配置room.generateKotlin=false,让KSP生成Java代码以规避该bug

内容的提问来源于stack exchange,提问作者Hector

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 17:54:54