以下に示すように、基本インターフェイスで共通の [〜#〜] 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
インターフェイス Room は、基本インターフェイスから継承します。
_@Dao
interface ProductDao : BaseDao<Product> {
// Specific methods
}
_
fun createAll(objects: List<I>)
の定義をコンパイルすると、次のエラーが発生します。
パラメータのタイプは、@ Entityで注釈が付けられたクラスまたはそのコレクション/配列である必要があります。
関数に@JvmSuppressWildcards
を追加してみてください。
@Insert
@JvmSuppressWildcards
fun createAll(objects: List<I>)
ドキュメントから:
たとえばCollectionのように、宣言サイトに差異があるパラメーターに対応する型引数のワイルドカードを生成または省略するようにコンパイラーに指示します。
宣言がJavaからの使用に不便であると思われる場合にのみ役立つ場合があります。
次の方法で問題を解決しました:
@Dao
interface BaseDao<T> {
/**
* Insert a list in the database. If the item already exists, replace it.
*
* @param list the items to be inserted.
*/
@Insert(onConflict = OnConflictStrategy.REPLACE)
@JvmSuppressWildcards
abstract fun insertAll(kist: List<T>)
}
@ JvmSuppressWildcards私のためにトリックを行いました
追加する必要があります@Entity
モデルクラスの注釈(Daoメソッドには具体的なモデルクラスが必要です)ですが、インターフェースでジェネリックを使用しますBaseDao<in I>
。 https://developer.Android.com/training/data-storage/room/defining-data.html
私の修正は、問題が解決するまでJavaにBaseDao
インターフェイスを実装することでした。
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);
}
Kotlinのアブストラクト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\")")
}
できます!
私は同じ問題を抱えていて、解決策を見つけたと思います:
Kotlinが汎用オブジェクトの配列を作成することは不可能であるため、そのような回避策を講じる必要があります。
@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>)
ジェネリックではなく実際のオブジェクトを使用している限り、同様に機能します。