首页 > 解决方案 > 如何引用泛型类型的变量?

问题描述

我正在尝试为 Room 库实现“基本 DAO”接口,以避免样板代码:

BaseEntity.kt

interface BaseEntity {
    val entityName: String
}

笔记.kt

@Entity
class Note : BaseEntity {
    override val entityName: String = "note"
    ...
}

BaseDao.kt

interface BaseDao<T : BaseEntity> {
    @Query("SELECT * FROM ${T.entityName}")
    fun selectAll(): List<T>
    ...

}

NoteDao.kt

@Dao
interface NoteDao : BaseDao<Note> {
...
}

但是,表达式${T.entityName}无效。有没有办法做到这一点?

标签: androidkotlinandroid-room

解决方案


我不相信您可以实现“基本 DAO”接口。原因是Room 在编译时创建了每个 DAO 实现。因此,为什么您会收到消息An annotation argument must be a compile time-constant

Room 需要从注解中(例如)知道哪些表列映射到哪些变量以及用于执行映射的方法,以便可以生成底层代码。

例如,如果实体和道是:-

@Entity
class Note {

    @PrimaryKey
    var entityName: String = ""

}

@Dao
interface BaseDao {
    @Query("SELECT * FROM Note")
    fun selectAll(): List<Note>

}

那么底层生成的java将是: -

public final class BaseDao_Impl implements BaseDao {
  private final RoomDatabase __db;

  public BaseDao_Impl(RoomDatabase __db) {
    this.__db = __db;
  }

  @Override
  public List<Note> selectAll() {
    final String _sql = "SELECT * FROM Note";
    final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 0);
    __db.assertNotSuspendingTransaction();
    final Cursor _cursor = DBUtil.query(__db, _statement, false, null);
    try {
      final int _cursorIndexOfEntityName = CursorUtil.getColumnIndexOrThrow(_cursor, "entityName");
      final List<Note> _result = new ArrayList<Note>(_cursor.getCount());
      while(_cursor.moveToNext()) {
        final Note _item;
        _item = new Note();
        final String _tmpEntityName;
        _tmpEntityName = _cursor.getString(_cursorIndexOfEntityName);
        _item.setEntityName(_tmpEntityName);
        _result.add(_item);
      }
      return _result;
    } finally {
      _cursor.close();
      _statement.release();
    }
  }
}

推荐阅读