我尝试在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
)
Clouds.kt
data class Clouds(
val all: Int
)
Coord.kt
data class Coord(
val lat: Double,
val lon: Double
)
Main.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
)
Sys.kt
data class Sys(
val country: String,
val id: Int,
val sunrise: Int,
val sunset: Int,
val type: Int
)
Weather.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)
}
}
}
3条答案
按热度按时间jchrr9hc1#
这是我在Kotlin的转换器:
其中
.convertToJson()
和.fromJson(str)
作为Value
类中的扩展实现:您应该为每个非本机类类型实现
Converter
类。不要忘记在数据库上注册转换器:当您编译完代码并在以后引入新的更改时,您还必须增加
version
参数以使更改生效:以下是有关此主题的官方文档和培训:https://developer.android.com/training/data-storage/room
vlurs2pr2#
所以我使用了类型转换器类,但是我感到很困惑
SQLite(Room是一个面向对象的 Package 器)不是一个面向对象(或感知)的数据库。它是一个可以存储基本类型数据的数据库,这些数据是
因此,要存储坐标、云或天气类型......您有三个选项:
1.嵌入类,在这种情况下,将从嵌入类复制字段(如果嵌入类包含不支持的类型,则会很复杂)。答案中未涉及
1.将类作为一个表,在它自己的权限内,在它和父表(WeatherDTO)之间有一个关系。答案中未涉及
1.以将类转换为SQLite类型之一(其中TEXT或BLOB可能仅适用)。
考虑到选项3(TyepConverters)转换数据的作用很小(如果有),只使用存储数据,因为您将无法检索数据。
因此,类型转换器应始终成对使用。
因此,您需要相当多的类型转换器,即每个字段2个:-
它是Room查找相应类型转换器的字段的类。
转换对象(也称为类)最简单的方法之一是将对象转换为JSON表示形式。尽管这一方法的复杂性在于有许多JSON库,它们通常会有差异。
在下面的例子中,我们使用了Google的JSON库。但是,在Room中使用这个库似乎并不直接支持List的使用,<the_class>例如List。
implementation 'com.google.code.gson:gson:2.10'
作为一个新的类**
WeatherList
**已经按照如下使用:-WeatherDTO类已更改为按以下方式使用它:-
因此,TypeConverters类可以是:-
因此,所有不直接支持的类型/类/对象都将转换为类型/类/对象的JSON字符串表示,或从JSON字符串表示转换而来。
请注意,您需要添加
@TypeConverters(@TypeConverters( value = [<????>.TypeConverters::class])
。其中必须区分您的项目TypeConverters类和Room的 (TypeConverters可能不是该类的最佳名称,重命名它将克服区分的需要)工作示例
下面将把上述内容付诸实施。
由于该问题不包括基本类别,因此使用了以下内容:
@道注解界面也是由简单的:-
此外,@Database注解抽象类是由以下内容组成的:
最后一些活动代码实际做一些事情(存储和检索一些数据):-
结果
运行时,日志包含预期内容:-
使用App Inspection,则数据库如下所示:-
qgelzfjb3#
接上一个答案**@嵌入式与类型转换器**
从前面的回答中可以看出,使用TypeConverters存在一些问题。从数据库的Angular 来看,TypeConverters将不可避免地包含与标准化相反的膨胀/不必要的数据(而不是不必要地存储重复数据)。
举个例子,JSON表示法对于每一行都包含完全相同的字段名,这浪费了存储空间,所有行都将有存储分隔符的额外开销(
[
s和]
s,{
s和}
s,(一个月四个月一个月一个月一个月)。此外,由于膨胀并且还由于多个值被存储在单个列中,因此实际使用所存储的数据可能变得复杂,并且因此可能限制性。如果不存储膨胀数据,效率会更高,而且从数据库的Angular (查询数据以进行检索)来看,如果不在单个列中存储多个值,则可以消除复杂性并增强存储数据的可用性。
使用
@Embedded
注解可以非常容易地消除膨胀。请考虑以下内容(WeatherDTO类/实体的替代版本):-除了weather字段,我们所做的就是添加@Embedded注解。注意字段的类都有Room直接支持的字段类型。
将此实体添加到
@Database
注解中,并在@Dao
注解类中添加几个附加函数,如下所示:然后修改活动代码,以包括:
现在日志中的结果包括:-
然而,数据现在存储在数据库中,如下所示(忽略天气字段):-