Intereting Posts

Kotlin: Как вставить список объектов в комнату?

Я пытаюсь определить общие методы CRUD в базовом интерфейсе, как показано здесь:

interface BaseDao<in I> { @Insert(onConflict = OnConflictStrategy.REPLACE) fun create(obj: I) @Insert(onConflict = OnConflictStrategy.REPLACE) fun createAll(objects: List<I>) @Delete fun delete(obj: I) } 

Следующий интерфейс ProductDao для комнаты наследует от базового интерфейса:

 @Dao interface ProductDao : BaseDao<Product> { // Specific methods } 

Когда я компилирую определение для fun createAll(objects: List<I>) возникает следующая ошибка:

Тип параметра должен быть классом, аннотированным с @Entity или его набором / массивом.

Вы должны добавить аннотацию @Entity для своего класса модели (у вас должен быть конкретный класс модели для методов Dao), но вы используете дженерики в вашем интерфейсе BaseDao<in I> . https://developer.android.com/training/data-storage/room/defining-data.html

У меня была такая же проблема, и я считаю, что нашел решение:

Котлин не может создать массив из общих объектов, поэтому вам необходимо сделать такое обходное решение:

 @Insert(onConflict = OnConflictStrategy.REPLACE) fun create(obj: I) @Transaction fun createAll(objects: List<I>) = objects.forEach {insert(it)} 

@Transaction должно заставить все это произойти в одной транзакции, поэтому оно не должно вводить какие-либо проблемы с производительностью, но я не уверен в этом.

Более того, просто:

 @Insert(onConflict = OnConflictStrategy.REPLACE) fun createAll(objects: List<Product>) 

будет работать так же, пока он использует реальные объекты, а не дженерики.

Мое решение заключалось в том, чтобы реализовать интерфейс BaseDao на Java до тех пор, пока проблема не исчезнет.

 public interface IBaseDao<T> { @Insert(onConflict = OnConflictStrategy.REPLACE) @WorkerThread void save(T item); @Delete @WorkerThread void delete(T item); @Delete @WorkerThread void deleteAll(List<T> items); @Insert(onConflict = OnConflictStrategy.REPLACE) @WorkerThread void saveAll(List<T> items); } 

Абстрактный BaseDao в Котлине

 abstract class BaseDao<T> : IBaseDao<T> { @WorkerThread open fun getAll(): List<T> = TODO("Override and place the annotation @Query. Ex: @Query(\"SELECT * FROM Model\")") @WorkerThread open fun loadAll(): LiveData<List<T>> = TODO("Override and place the annotation @Query. Ex: @Query(\"SELECT * FROM Model\")") } 

Оно работает!