我创建了一个虚拟实体类:
@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
}
}
或者类似的东西。那么它是怎么知道的呢?
你说:-
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 函数。