房间不会自动生成主键

时间:2018-03-25 12:51:02

标签: java android kotlin android-room

我的API响应中包含以下模型

{ 'the': 1, 'me': 2, 'a': 3 ..... }

天气回购 从本地或远程数据源获取数据,我将@Entity(tableName = TABLE_NAME) class WeatherEntry { @PrimaryKey(autoGenerate = true) var wID: Long? = null @SerializedName("dt") @ColumnInfo(name = COLUMN_DATE) var date: String = "" @SerializedName("city") @Embedded(prefix = "location_") var location: Location? = null @SerializedName("main") @Embedded(prefix = "main_") var main: Main? = null @SerializedName("weather") @TypeConverters(Converters::class) @Embedded(prefix = "weather_") var weather: ArrayList<Weather>? = null @SerializedName("wind") @Embedded(prefix = "wind_") var wind: Wind? = null } 设置为forceRemote,否则首先不会显示数据。

true

本地数据源

class WeatherRepository @Inject constructor(@Local var localDataSource: WeatherDataSource, @Remote var remoteDataSource: WeatherDataSource) :
    WeatherDataSource {

   private var caches: MutableList<WeatherEntry> = mutableListOf()
   override fun getWeatherEntries(location: String, forceRemote: Boolean): Flowable<MutableList<WeatherEntry>> {

        if (forceRemote) {
            return refreshData(location)
        } else {
            return if (caches.isNotEmpty()) {
                // if cache is available, return it immediately
                Flowable.just(caches)
            } else {
                // else return data from local storage
                localDataSource.getWeatherEntries(location, false)
                    .take(1)
                    .flatMap(({ Flowable.fromIterable(it) }))
                    .doOnNext { question -> caches.add(question) }
                    .toList()
                    .toFlowable()
                    .filter({ list -> !list.isEmpty() })
                    .switchIfEmpty(refreshData(location)) // If local data is empty, fetch from remote source instead.
            }
        }
    }

    /**
     * Fetches data from remote source.
     * Save it into both local database and cache.
     *
     * @return the Flowable of newly fetched data.
     */
    private fun refreshData(location: String): Flowable<MutableList<WeatherEntry>> {

        return remoteDataSource.getWeatherEntries(location,true).doOnNext({

            // Clear cache
            caches.clear()
            // Clear data in local storage
            localDataSource.deleteAllWeatherEntries()
        }).flatMap(({ Flowable.fromIterable(it) })).doOnNext({ entry ->
            caches.add(entry)
            localDataSource.insertWeatherEntry(entry)
        }).toList().toFlowable()
    }

远程数据源 这个肯定有效,因为我从api获得所有信息。

class WeatherLocalDataSource @Inject constructor(private var weatherDao: WeatherDao): WeatherDataSource {

    override fun insertWeatherEntry(weatherEntry: WeatherEntry) {
        return weatherDao.insert(weatherEntry)
    }

    ...
}

DAO

class WeatherRemoteDataSource @Inject constructor(var weatherService: WeatherService) :
    WeatherDataSource {

    override fun getWeatherEntries(location: String, forceRemote: Boolean): Flowable<MutableList<WeatherEntry>> {
        return weatherService.getForecast(
            location,
            "json",
            "metric",
            BuildConfig.OPEN_WEATHER_MAP_API_KEY
        ).map(WeatherForecastResponse::weatherEntries)
    }
}

**数据库**

@Dao
interface WeatherDao {

    ...

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insert(weatherEntry: WeatherEntry)
}

所有其他字段均可正常运行,但@Database( entities = [(WeatherEntry::class)], version = 1 ) abstract class WeatherDatabase : RoomDatabase() { abstract fun weatherDao(): WeatherDao } 始终为空。我的实施有什么问题?

我已经尝试将其默认值更改为wID并将类型更改为Int,但这也无效。

3 个答案:

答案 0 :(得分:2)

尝试使id不可为空:

 @PrimaryKey(autoGenerate = true)
    var wID: Long = 0

修改 我在示例代码here中找到了这个。 你可以使你的@Insert方法返回插入的行对象的id,所以你可以这样做:

在你的道中:

@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(weatherEntry: WeatherEntry) : Long

在刷新数据方法中:

private fun refreshData(location: String): Flowable<MutableList<WeatherEntry>> {

        return remoteDataSource.getWeatherEntries(location,true).doOnNext({

            // Clear cache
            caches.clear()
            // Clear data in local storage
            localDataSource.deleteAllWeatherEntries()
        }).flatMap(({ Flowable.fromIterable(it) })).doOnNext({ entry ->

            val entryID = localDataSource.insertWeatherEntry(entry)
            entry.wID = entryID
            caches.add(entry)
        }).toList().toFlowable()
    }

答案 1 :(得分:0)

我们使用这种方式:

实体定义中的

@PrimaryKey(autoGenerate = true)和

entity.id = ourDatabaseContext.entityDao().insert(entity);

答案 2 :(得分:0)

阅读https://developer.android.com/reference/androidx/room/PrimaryKey?hl=en#autoGenerate() ,您将得到答案

public boolean autoGenerate ()
Set to true to let SQLite generate the unique id.

When set to true, the SQLite type affinity for the field should be INTEGER.

If the field type is long or int (or its TypeConverter converts it to a long or int), Insert methods treat 0 as not-set while inserting the item.

If the field's type is Integer or Long (or its TypeConverter converts it to an Integer or a Long), Insert methods treat null as not-set while inserting the item.