【问题标题】:Android Room Entity Enum Field Causes Build FailedAndroid Room Entity Enum 字段导致构建失败
【发布时间】:2021-12-30 09:57:29
【问题描述】:

我注意到由于Room 2.3.0-alpha04 它支持EntityEnum 字段(来自此post),所以我尝试但失败了...

我的Gender枚举:

enum class Gender(val value: String) {
    MALE("Male"),
    FEMALE("Female"),
    UNKNOWN("Unknown")
}

我的Entitiy

@Entity(tableName = "student")
data class Student(
    var name: String,
    var age: Int,
    var gender: Gender    //<- Enum
) {
    @PrimaryKey(autoGenerate = true)
    var id: Long = 0
}

我的Dao

@Dao
interface StudentDao {
    @Query("SELECT * FROM student")
    fun getAllStudentsFlow(): Flow<List<Student>>

    @Insert
    suspend fun insert(student: Student)

    @Query("SELECT COUNT(name) FROM student WHERE name = :name")
    suspend fun getNameCount(name: String): Int
}

我使用的是最新版本:

implementation "androidx.room:room-runtime:2.4.0-beta02"
implementation "androidx.room:room-ktx:2.4.0-beta02"
kapt "androidx.room:room-compiler:2.4.0-beta02"

得到这个错误:

> Task :app:compileDebugJavaWithJavac FAILED
 C:\...\com\example\roomwithenum\database\StudentDao_Impl.java:87: ����: �޷����� 
Student�еĹ����� StudentӦ�õ���������;
            _item = new Student();
                ^
  ��Ҫ: String,int,Gender
  �ҵ�: û�в���
  ԭ��: ʵ�ʲ����б����ʽ�����б��Ȳ�ͬ
1 ������

任何帮助将不胜感激。

【问题讨论】:

  • 我在您粘贴的错误中看到的主要是问号。你能把它更新成正确的格式吗?

标签: android kotlin enums android-room android-database


【解决方案1】:

所以我尝试但失败了......

按照以下方式使用您的代码和依赖项:-

dependencies {

    implementation 'androidx.core:core-ktx:1.7.0'
    implementation 'androidx.appcompat:appcompat:1.3.1'
    implementation 'com.google.android.material:material:1.4.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
    implementation 'androidx.room:room-ktx:2.4.0-beta02'
    implementation 'androidx.room:room-runtime:2.4.0-beta02'
    implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.4.0'
    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0'
    implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.0'
    implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0'
    implementation 'androidx.lifecycle:lifecycle-viewmodel-savedstate:2.4.0'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
    kapt 'androidx.room:room-compiler:2.4.0-beta02'
    kapt 'androidx.lifecycle:lifecycle-compiler:2.4.0'
}

然后它可以正常编译,并且在您的情况下出现乱码的 StudentDao_Impl 部分编译为 ):-

  @Override
  public List<Student> call() throws Exception {
    final Cursor _cursor = DBUtil.query(__db, _statement, false, null);
    try {
      final int _cursorIndexOfName = CursorUtil.getColumnIndexOrThrow(_cursor, "name");
      final int _cursorIndexOfAge = CursorUtil.getColumnIndexOrThrow(_cursor, "age");
      final int _cursorIndexOfGender = CursorUtil.getColumnIndexOrThrow(_cursor, "gender");
      final int _cursorIndexOfId = CursorUtil.getColumnIndexOrThrow(_cursor, "id");
      final List<Student> _result = new ArrayList<Student>(_cursor.getCount());
      while(_cursor.moveToNext()) {
        final Student _item;
        final String _tmpName;
        if (_cursor.isNull(_cursorIndexOfName)) {
          _tmpName = null;
        } else {
          _tmpName = _cursor.getString(_cursorIndexOfName);
        }
        final int _tmpAge;
        _tmpAge = _cursor.getInt(_cursorIndexOfAge);
        final Gender _tmpGender;
        _tmpGender = __Gender_stringToEnum(_cursor.getString(_cursorIndexOfGender));
        _item = new Student(_tmpName,_tmpAge,_tmpGender);
        final long _tmpId;
        _tmpId = _cursor.getLong(_cursorIndexOfId);
        _item.setId(_tmpId);
        _result.add(_item);
      }
      return _result;
    } finally {
      _cursor.close();
    }
  }

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

大约 2/3 后是行 _item = new Student(_tmpName,_tmpAge,_tmpGender);

你的在这个阶段是乱码,但有趣的是显示 _item = new Student(); 好像 _tmpName _tmpAge 和 _tmpGender 不存在。

乱码数据就好像一个字节流破坏了生成的代码。

我建议尝试清理并重建,也许退出 Android Studio 并返回。您的代码似乎没有任何问题

----

附:您对 TypeConverters 发表评论说 我认为新版本默认会自动提供此功能...

你是对的,在 StudentDao_Impl 中它包括:-

  private String __Gender_enumToString(final Gender _value) {
    if (_value == null) {
      return null;
    } switch (_value) {
      case MALE: return "MALE";
      case FEMALE: return "FEMALE";
      case UNKNOWN: return "UNKNOWN";
      default: throw new IllegalArgumentException("Can't convert enum to string, unknown enum value: " + _value);
    }
  }

  private Gender __Gender_stringToEnum(final String _value) {
    if (_value == null) {
      return null;
    } switch (_value) {
      case "MALE": return Gender.MALE;
      case "FEMALE": return Gender.FEMALE;
      case "UNKNOWN": return Gender.UNKNOWN;
      default: throw new IllegalArgumentException("Can't convert value to enum, unknown value: " + _value);
    }
  }

附:我还将您的代码包含在另一个答案中,该答案已编译并使用 beta02 运行并显示(单击插入几次后):-

所以你的代码肯定没有问题。

【讨论】:

  • 非常感谢您的详细解答!原来我把Gender类放在了包名enum里面,这不是一个有效的包名……重命名包后,一切顺利。
【解决方案2】:

将枚举以字符串等原始类型存储在 DB 中。对你来说最好的做法是使用@TypeConverters

class TypeConverters {

     @TypeConverter
     fun toGender(value: String) = enumValueOf<Gender>(value)

     @TypeConverter
     fun fromGender(value: Gender) = value.name
}

并使用注释您的数据库类

@TypeConverters(Converters::class)

参考https://developer.android.com/reference/android/arch/persistence/room/TypeConverter

【讨论】:

  • 我以为新版本会默认自动提供这个...
猜你喜欢
  • 1970-01-01
  • 2018-04-22
  • 2016-04-13
  • 2019-09-21
  • 1970-01-01
  • 2020-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多