До сих пор для хранения в База данных номеров я использовал преобразователь типов для каждого класса. Как это:
@SerializedName("sidebar")
@Expose
@TypeConverters(SidebarConverter.class)
private Sidebar sidebar;
@SerializedName("splash")
@Expose
@TypeConverters(SplashConverter.class)
private Splash splash;
@SerializedName("overview")
@Expose
@TypeConverters(OverviewConverter.class)
private Overview overview;
@SerializedName("home")
@Expose
@TypeConverters(HomeConverter.class)
private Home home;
@SerializedName("portfolio")
@Expose
@TypeConverters(PortfolioConverter.class)
private Portfolio portfolio;
@SerializedName("team")
@Expose
@TypeConverters(TeamConverter.class)
private Team team;
Я хочу знать, есть ли более удобный способ использовать один TypeConverter в одиночку в базе данных.
Вы можете определить весь свой преобразователь в одном классе следующим образом:
public class DateTypeConverter {
@TypeConverter
public static Date toDate(Long value) {
return value == null ? null : new Date(value);
}
@TypeConverter
public static Long toLong(Date value) {
return value == null ? null : value.getTime();
}
}
А затем установите этот конвертер в базе данных вашей комнаты с такой аннотацией @TypeConverter, которая работает глобально с любым классом @Entity. Вам не нужно определять @TypeConverter индивидуально в классе Entity.
@Database(entities = {Product.class}, version = 1)
@TypeConverters({DateTypeConverter.class})
public abstract class MyDatabase extends RoomDatabase {
public abstract ProductDao productDao();
}
Обратите внимание, что мы добавили новую аннотацию с именем @TypeConverters в определение нашей базы данных, чтобы указать различные преобразователи, которые у нас могут быть (вы можете разделить ее запятыми и добавить другие).
Либо вы можете поместить все это в один класс, либо, если у вас уже есть несколько классов для нескольких конвертеров, вы можете ссылаться на разные конвертеры через запятую в @TypeConverters({SidebarConverter.class,SplashConverter.class,PortfolioConverter.class}).
Так что по-прежнему много повторяющегося кода. Значит, нет универсального способа?
Нет, на данный момент нет универсального способа, но этот подход имеет меньше шаблонного кода, чем ваша текущая реализация. Он определяет ваши преобразователи глобально, а не для каждого объекта в классе Entity
Проблема здесь в том, что генерация кода Room пытается найти определенный тип, и если вы попытаетесь создать универсальный конвертер, ему не удастся сгенерировать соответствующие методы. Однако, если в вашем случае уместно преобразовать данные в json для хранения, вы можете уменьшить шаблон следующим образом:
@TypeConverter
fun toSomething(value: String): Something = fromJson(value)
@TypeConverter
fun fromSomething(value: Something): String = toJson(value)
fromJson и toJson являются общими, например они могут выглядеть так. Каждый раз, когда вам нужно добавить типы, просто воспользуйтесь двумя описанными выше методами и замените «Something» своим типом. Если у вас есть много классов для преобразования, вы можете довольно легко даже использовать TypeConverters для генерации кода, чтобы удовлетворить потребности генерации кода Room.
inline fun <reified T> fromJson(value: String): T {
val jsonAdapter = moshi.adapter(T::class.java)
return jsonAdapter.fromJson(value)
}
inline fun <reified T> toJson(value: T): String {
val jsonAdapter = moshi.adapter(T::class.java)
return jsonAdapter.toJson(value)
}
К сожалению, это решение не работает с комнатой. Ошибка: e: /Users/adamhurwitz/Code/CryptoTweets/app/build/tmp/kapt3/stubs/debug/app/cryptotweets/feed/models/entities/Entities.java:8: error: Cannot figure out how to save this field into database. You can consider adding a type converter for it.
Но для каждого класса будут разные методы. Что вы говорите о создании класса и копировании всех остальных кодов
@TypeConvertersдля разных классов в этот конкретный класс?