Room 如何知道如何将 TypeConverter 函数与适当的数据类型相匹配?

问题描述 投票:0回答:1

我创建了一个虚拟实体类:

@Entity
data class Entity(
    @PrimaryKey
    val id: Long?=null,
    val data1: DataClass1? = null,
    val data2: DataClass2? = null
)

data class DataClass1(
    val text: String = "",
    val c: Char = ' '
)

data class DataClass2(
    val num1: Float = 0.0f,
    val num2: Long = 0,
)

然后我创建了一个 Converter 类:

@ProvidedTypeConverter
class Converters {
    @TypeConverter
    fun A_YYYYY(json: String): DataClass2 = Gson().fromJson(json, DataClass2::class.java)
    @TypeConverter
    fun Z_YYYYY(data: DataClass2): String = Gson().toJson(data)
    @TypeConverter
    fun A_XXXXX(json: String): DataClass1 = Gson().fromJson(json, DataClass1::class.java)
    @TypeConverter
    fun Z_XXXXX(data: DataClass1): String = Gson().toJson(data)
}

我故意给这些方法起了无意义的名称并更改了顺序 - DataClass2 的转换器方法是第一个,DataClass1 的转换器方法是第二个(与实体类中的顺序相反)。

那么 Room 如何知道如何匹配生成文件中的方法呢? 自动生成文件 Dao_Impl 中的代码:

  @Override
  public Object getEntityById(final long id, final Continuation<? super Entity> arg1) {
    final String _sql = "SELECT * FROM entity WHERE id = ?";
    final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 1);
    int _argIndex = 1;
    _statement.bindLong(_argIndex, id);
    final CancellationSignal _cancellationSignal = DBUtil.createCancellationSignal();
    return CoroutinesRoom.execute(__db, false, _cancellationSignal, new Callable<Entity>() {
      @Override
      @Nullable
      public Entity call() throws Exception {
        final Cursor _cursor = DBUtil.query(__db, _statement, false, null);
        try {
          final int _cursorIndexOfId = CursorUtil.getColumnIndexOrThrow(_cursor, "id");
          final int _cursorIndexOfData1 = CursorUtil.getColumnIndexOrThrow(_cursor, "data1");
          final int _cursorIndexOfData2 = CursorUtil.getColumnIndexOrThrow(_cursor, "data2");
          final Entity _result;
          if (_cursor.moveToFirst()) {
            final Long _tmpId;
            if (_cursor.isNull(_cursorIndexOfId)) {
              _tmpId = null;
            } else {
              _tmpId = _cursor.getLong(_cursorIndexOfId);
            }
            final DataClass1 _tmpData1;
            final String _tmp;
            if (_cursor.isNull(_cursorIndexOfData1)) {
              _tmp = null;
            } else {
              _tmp = _cursor.getString(_cursorIndexOfData1);
            }
            _tmpData1 = __converters().A_XXXXX(_tmp);
            final DataClass2 _tmpData2;
            final String _tmp_1;
            if (_cursor.isNull(_cursorIndexOfData2)) {
              _tmp_1 = null;
            } else {
              _tmp_1 = _cursor.getString(_cursorIndexOfData2);
            }
            _tmpData2 = __converters().A_YYYYY(_tmp_1);
            _result = new Entity(_tmpId,_tmpData1,_tmpData2);
          } else {
            _result = null;
          }
          return _result;
        } finally {
          _cursor.close();
          _statement.release();
        }
      }
    }, arg1);
  }

 private synchronized Converters __converters() {
    if (__converters == null) {
      __converters = __db.getTypeConverter(Converters.class);
    }
    return __converters;
  }

转换器功能与数据匹配的具体部分:

 final int _cursorIndexOfData1 = CursorUtil.getColumnIndexOrThrow(_cursor, "data1");
 final int _cursorIndexOfData2 = CursorUtil.getColumnIndexOrThrow(_cursor, "data2");


//.............................
 if (_cursor.isNull(_cursorIndexOfData1)) {
              _tmp = null;
            } else {
              _tmp = _cursor.getString(_cursorIndexOfData1);
            }
            _tmpData1 = __converters().A_XXXXX(_tmp);

//.............................

if (_cursor.isNull(_cursorIndexOfData2)) {
              _tmp_1 = null;
            } else {
              _tmp_1 = _cursor.getString(_cursorIndexOfData2);
            }
            _tmpData2 = __converters().A_YYYYY(_tmp_1);

没有:

__converters().forEach{ it ->
    if(_tmp_1.dataType == it.dataType){
          //some code
        }
}

或者类似的东西。那么它是怎么知道的呢?

android android-room typeconverter
1个回答
0
投票

你说:-

There isn't any:

__converters().forEach{ it ->
    if(_tmp_1.dataType == it.dataType){
          //some code
        }
}

这是因为关于应用什么类型转换器的决定是在编译时做出的,因此你有:-

_tmpData1 = __converters().A_XXXXX(_tmp);

然后:-

_tmpData2 = __converters().A_YYYYY(_tmp_1);

至于如何决定,是根据函数签名中的类型(插入时的参数类型和检索时的返回类型)与要插入/提取的类的类型相匹配。

所以

val data1: DataClass1? = null,
DataClass1的类型,因此使用函数A_XXXXX,因为在提取数据时它返回DataClass1的类型。当插入数据时,同样通过签名/类型,它将利用 Z_XXXXX 函数。

© www.soinside.com 2019 - 2024. All rights reserved.