我试图在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)
}
}
}发布于 2022-11-10 12:53:14
,所以我使用的是类型转换器类,但是我感到困惑。
SQLite (其周围的数据库是面向对象的包装器)不是面向对象的(或感知的)数据库。它是一个数据库,它可以存储数据的基本类型,这些数据类型是
因此,存储一种Coord,云或天气.你有三种选择:-
考虑到转换数据的选项3 (TyepConverters)很少(如果有的话),只使用存储数据,因为您将无法检索数据。
因此,应始终对转换器进行配对。
。
因此,您将需要相当多的类型转换器,即每个字段需要2台:-
Clouds)
H 143风(类风)<代码>H 244<代码>F 245
房间查看的是字段的类,以找到相应的类型转换器。
转换对象(也称为类)的最简单方法之一是将对象转换为JSON表示。虽然这方面的一个复杂性是有许多JSON库,而且它们通常会有差异。
对于下面的例子,已经使用了JSON库。然而,这个库的使用似乎并不直接支持使用List,例如List。
这个依赖项(例如,implementation 'com.google.code.gson:gson:2.10' )
作为绕过一个新类,WeatherList使用了如下所示:-
data class WeatherList(
val weatherList: List<Weather>
)WeatherDTO类已经更改为使用它,如下所示:-
....
//val weather: List<Weather>,
val weather: WeatherList,
....因此,TypeConverters类可以是:-
class TypeConverters {
@TypeConverter
fun fromCloudsToJSONString(clouds: Clouds): String = Gson().toJson(clouds)
@TypeConverter
fun toCloudsFromJSONString(jsonString: String): Clouds = Gson().fromJson(jsonString,Clouds::class.java)
@TypeConverter
fun fromCoordToJSONString(coord: Coord): String = Gson().toJson(coord)
@TypeConverter
fun toCoordFromJSONString(jsonString: String): Coord = Gson().fromJson(jsonString,Coord::class.java)
@TypeConverter
fun fromMaintoJSONString(main: Main): String = Gson().toJson(main)
@TypeConverter
fun toMainFromJSONString(jsonString: String): Main = Gson().fromJson(jsonString,Main::class.java)
@TypeConverter
fun fromSysToJSONString(sys: Sys): String = Gson().toJson(sys)
@TypeConverter
fun toSysFromJSONString(jsonString: String): Sys = Gson().fromJson(jsonString,Sys::class.java)
@TypeConverter
fun fromWeatherListFromJSONString(weatherList: WeatherList): String = Gson().toJson(weatherList)
@TypeConverter
fun toWeatherListFromJSOnString(jsonString: String): WeatherList = Gson().fromJson(jsonString,WeatherList::class.java)
@TypeConverter
fun fromWindToJSONString(wind: Wind): String = Gson().toJson(wind)
@TypeConverter
fun toWindFromJSONString(jsonString: String): Wind = Gson().fromJson(jsonString,Wind::class.java)
}因此,所有不受直接支持的类型/类/对象都转换为/从类型/类/对象的JSON字符串表示形式转换。
请注意,您需要添加@TypeConverters(@TypeConverters( value = [<????>.TypeConverters::class])。在哪里必须区分您的项目-- TypeConverters类和Room类(TypeConverters可能不是该类的最佳名称,重新命名它,就可以克服区分的需要)
工作示例
以下内容将上述内容付诸实施。
由于问题中不包括底层类,因此使用了以下内容:
data class Coord(
val longitude: Double,
val latitude: Double
)
data class Clouds(
val cover: Double,
val type: String
)
data class Main(
val main: Double
)
data class Sys(
val sys: Double
)
data class WeatherList(
val weatherList: List<Weather>
)
data class Weather(
val weather: Double
)
data class Wind(
val wind: Double
)@Dao注释的接口也是由以下内容组成的:
@Dao
interface AllDao {
@Insert(onConflict = OnConflictStrategy.IGNORE)
fun insert(weatherDTO: WeatherDTO)
@Query("SELECT * FROM weatherdb")
fun getAllFromWeatherDB(): List<WeatherDTO>
}此外,@Database注释的抽象类是:-
@TypeConverters( value = [a.a.so74384736typeconverterconfusion.TypeConverters::class])
@Database(entities = [WeatherDTO::class], exportSchema = false, version = 1)
abstract class TheDatabase: RoomDatabase() {
abstract fun getAllDao(): AllDao
companion object {
private var instance: TheDatabase? = null
fun getInstance(context: Context): TheDatabase {
if (instance==null) {
instance = Room.databaseBuilder(context,TheDatabase::class.java,"the_database.db")
.allowMainThreadQueries()
.build()
}
return instance as TheDatabase
}
}
}最后一些实际操作的活动代码(存储和检索一些数据):-
class MainActivity : AppCompatActivity() {
lateinit var db: TheDatabase
lateinit var dao: AllDao
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
db = TheDatabase.getInstance(this)
dao = db.getAllDao()
dao.insert(
WeatherDTO(
"base001",
Clouds(25.5,"cumulus"),10,
Coord(10.567,30.345),
11,
12,
Main(12345.67890),
"thename",
Sys(9.87654321),
14,
1000,
WeatherList(listOf(Weather(5.1234),Weather(6.5432), Weather(7.6543))),
Wind(23.12)
)
)
for (wdto in dao.getAllFromWeatherDB()) {
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 ....通过应用程序检查,数据库如下所示:

转换为JSON字符串的字段是highlighted.
发布于 2022-11-10 07:40:12
这是我在科特林的转换器:
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() {这里是关于这个主题的正式文档,甚至是培训:https://developer.android.com/training/data-storage/room
发布于 2022-11-11 01:06:38
按照前面的答案@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 ....的相同数据。
然而,数据现在以下列形式存储在数据库中(忽略天气字段):

advantageous).
https://stackoverflow.com/questions/74384736
复制相似问题