我正在嘗試在 Android (Kotlin) 中使用型別轉換器,所以我正在使用型別轉換器類,但我很困惑,就像在云內部一樣,我只有一個變數,所以我已經回傳它但是
@Entity(tableName = "WeatherDb")
data class WeatherDTO(
val base: String,
val clouds: Clouds,
val cod: Int,
val coord: Coord,
val dt: Int,
@PrimaryKey(autoGenerate = true)
val id: Int,
val main: Main,
val name: String,
val sys: Sys,
val timezone: Int,
val visibility: Int,
val weather: List<Weather>,
val wind: Wind
)
class TypeConverters {
@TypeConverter
fun fromCloudsToDouble(clouds: Clouds): Int {
return clouds.all
}
fun fromCoordToDouble(coord: Coord): Double {
}
}
在 coord 類中,這里有多個具有不同資料型別的如何隱藏這個?
data class Main(
val feels_like: Double,
val grnd_level: Int,
val humidity: Int,
val pressure: Int,
val sea_level: Int,
val temp: Double,
val temp_max: Double,
val temp_min: Double
)
云.kt
data class Clouds(
val all: Int
)
坐標.kt
data class Coord(
val lat: Double,
val lon: Double
)
主.kt
data class Main(
val feels_like: Double,
val grnd_level: Int,
val humidity: Int,
val pressure: Int,
val sea_level: Int,
val temp: Double,
val temp_max: Double,
val temp_min: Double
)
系統.kt
data class Sys(
val country: String,
val id: Int,
val sunrise: Int,
val sunset: Int,
val type: Int
)
天氣.kt
data class Weather(
val description: String,
val icon: String,
val id: Int,
val main: String
)
Wind.kt
data class Wind(
val deg: Int,
val gust: Double,
val speed: Double
)
WeatherViewModel.kt
@HiltViewModel
class WeatherViewModel @Inject constructor(
private val repo:WeatherRepository,
private val application: Application,
private val WeatherDb:WeatherDB,
private val fusedLocationProviderClient: FusedLocationProviderClient
) :ViewModel(){
private val _resp = MutableLiveData<WeatherDTO>()
val weatherResp:LiveData<WeatherDTO>
get() = _resp
private val _cord = MutableLiveData<Coord>()
val cord:LiveData<Coord>
get() = _cord
var locality:String = ""
fun getWeather(latitude:Double,longitude:Double) =
viewModelScope.launch {
repo.getWeather(latitude,longitude).let { response->
if(response.isSuccessful){
Log.d("response","${response.body()}")
WeatherDb.WeatherDao().insertWeather(response.body()!!)
_resp.postValue(response.body())
}else{
Log.d("Weather Error","getWeather Error Response: ${response.message()}")
}
}
}
fun fetchLocation():Boolean{
val task = fusedLocationProviderClient.lastLocation
if(ActivityCompat.checkSelfPermission(application,android.Manifest.permission.ACCESS_FINE_LOCATION)
!=PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(application,android.Manifest.permission.ACCESS_COARSE_LOCATION)
!=PackageManager.PERMISSION_GRANTED
){
return true
}
task.addOnSuccessListener {
if(it!=null){
getWeather(it.latitude,it.longitude)
getAddressName(it.latitude,it.longitude)
Log.d("localityname", locality)
}
}
return true
}
private fun fetchLocationDetails(){
}
private fun getAddressName(lat:Double,long:Double):String{
var addressName = " "
val geoCoder = Geocoder(application, Locale.getDefault())
val address = geoCoder.getFromLocation(lat,long,1)
if (address != null) {
addressName = address[0].adminArea
}
locality = addressName
Log.d("subadmin",addressName.toString())
Log.d("Address", addressName)
return addressName
}
fun getCoordinates(cord:String){
val geocoder = Geocoder(application,Locale.getDefault())
val address = geocoder.getFromLocationName(cord,2)
val result = address?.get(0)
if (result != null) {
getWeather(result.latitude,result.longitude)
getAddressName(result.latitude,result.longitude)
}
}
}
uj5u.com熱心網友回復:
這是我在 Kotlin 中的轉換器:
class Converters {
@TypeConverter
fun valueFromDomainToStorage(value: Value): String {
return value.convertToJson()
}
@TypeConverter
fun valueFromStorageToDomain(str: String): Value {
// we can not create an empty instance of value as TypeDecoder.java should call non-empty constructor
return Value(
"just a stub",
BigInteger.valueOf(0),
BigInteger.valueOf(0),
false,
BigInteger.valueOf(0)
)
.fromJson(str)
}
}
在哪里.convertToJson()并.fromJson(str)作為類中的擴展實作Value:
fun Value.convertToJson(): String {
val result = JSONObject()
result.put(ValueConst.OFFER_FIELD, offer)
result.put(ValueConst.AVAILABLE_SINCE, availableSince.toLong())
result.put(ValueConst.AVAILABLE_END, availabilityEnd.toLong())
result.put(ValueConst.IS_CONSUMED, isConsumed)
result.put(ValueConst.LOCKED_UNTIL, lockedUntil)
return result.toString()
}
fun Value.fromJson(json: String): Value {
val subj = JSONObject(json)
return Value(
subj.optString(ValueConst.OFFER_FIELD),
BigInteger.valueOf(subj.optLong(ValueConst.AVAILABLE_SINCE)),
BigInteger.valueOf(subj.optLong(ValueConst.AVAILABLE_END)),
subj.optBoolean(ValueConst.IS_CONSUMED),
BigInteger.valueOf(subj.optLong(ValueConst.LOCKED_UNTIL))
)
}
您應該Converter為每個非本地型別別實作類。不要忘記在資料庫中注冊您的轉換器:
@Database(entities = [ChainTransaction::class], version = 1, exportSchema = false)
@TypeConverters(Converters::class)
abstract class AppDatabase: RoomDatabase() {
當您編譯代碼并稍后引入新更改時,您也必須增加version引數才能使更改生效:
@Database(entities = [ChainTransaction::class], version = 2, exportSchema = false)
@TypeConverters(Converters::class)
abstract class AppDatabase: RoomDatabase() {
這是官方檔案,甚至是有關此主題的培訓:

- 轉換為 JSON 字串的欄位已突出顯示。
- 顯然,由于類的原因,資料很可能與您所期望的不完全一樣。
uj5u.com熱心網友回復:
繼續上一個答案@Embedded 與型別轉換器
從前面的回答可以看出,在使用 TypeConverters 方面存在一些問題。從資料庫的角度來看,TypeConverters 將不可避免地包含與規范化相反的膨脹/不必要的資料(而不是不必要地存盤重復資料)。
例如,每行的 JSON 表示將包含完全相同的欄位名稱,浪費存盤空間,所有行都將具有存盤分隔符([s 和]s、{s 和}s、:s ,s)的額外開銷。此外,由于膨脹以及多個值存盤在單個列中,實際使用存盤的資料可能會變得復雜,因此可能會受到限制。
不存盤膨脹會更有效,它可以消除復雜性并從資料庫的角度增強存盤資料的可用性(查詢資料以進行檢索),而不是在單個列中存盤多個值。
使用@Embedded注釋可以很容易地消除臃腫。考慮以下(WeatherDTO 類/物體的替代版本):-
@Entity(tableName = "WeatherDbAlternative1")
data class WeatherDTOAlternative1(
val base: String,
@Embedded
val clouds: Clouds,
val cod: Int,
@Embedded
val coord: Coord,
val dt: Int,
@PrimaryKey(autoGenerate = true)
val id: Int,
@Embedded
val main: Main,
val name: String,
@Embedded
val sys: Sys,
val timezone: Int,
val visibility: Int,
//val weather: List<Weather>,
/* Unable to embed directly so not embedding */
val weather: WeatherList,
@Embedded
val wind: Wind
)
在天氣欄位欄上所做的就是添加 @Embedded 注釋。注意欄位的類都有 Room 直接支持的型別的欄位。
將此物體添加到@Database注釋中并在注釋類中添加幾個附加函式,@Dao如下所示:-
@Query("SELECT * FROM weatherdbalternative1")
fun getAllFromWeatherDBAlternative1(): List<WeatherDTOAlternative1>
@Insert(onConflict = OnConflictStrategy.IGNORE)
fun insert(weatherDTOAlternative1: WeatherDTOAlternative1)
然后修改活動代碼以包括:-
/*ALTERNATIVE 1 All but WeatherList embedded */
dao.insert(
WeatherDTOAlternative1(
"base001A",
Clouds(25.5, "cumulus"),
10,
Coord(10.567, 30.345),
11,
12,
Main(12345.67890),
"thenameA1",
Sys(9.87654321),
14,
1000,
WeatherList(listOf(Weather(5.1234), Weather(6.5432), Weather(7.6543))),
Wind(23.12)
)
)
for (wdto in dao.getAllFromWeatherDBAlternative1()) {
Log.d(
"DBINFO",
"base = ${wdto.base} longitude = ${wdto.coord.longitude} latitude = ${wdto.coord.latitude} etc ...."
)
}
現在導致日志包括:-
D/DBINFO: base = base001 longitude = 10.567 latitude = 30.345 etc ....
D/DBINFO: base = base001A longitude = 10.567 latitude = 30.345 etc ....
- 即有效地存盤和檢索相同的資料
但是,資料現在以(忽略天氣欄位)的形式存盤在資料庫中:-

- 即存盤的資料更干凈,但以額外的列為代價(這可能是有利的)。
- 此外,雖然不明顯,但具有 @Embedded 注解的欄位不需要 TypeConverters。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/532648.html
上一篇:如何修復“java.lang.IllegalStateException:已執行”。PID:7664?
下一篇:在我的程序呼叫中型別轉換問題嗎?
