Null Arraylist from Room Database - android

I'm doing weather app in Kotlin, and in Activity is method which firstly takes cache data from Room, and after one hour data is updated. But there is problem probably with saving of data in database. I checked API logs in Profiles and there is no null with Weather List, so API works fine.
I'm trying to save Weather list as an ArrayList, but the answer from logs is still null. I also tried Type Converter, but still nothing. Maybe someone will find the reason for my problem and the answer.
EDIT: I removed #Embedded(prefix = "weather_") above the ArrayList and it works.
CurrentWeather (stores Weather ArrayList):
#Entity(tableName = "current_weather")
data class CurrentWeather(
#Embedded(prefix = "weather_")
val weather: ArrayList<Weather>? = ArrayList(), //here is my problem
#SerializedName("base")
val base: String,
#Embedded(prefix = "clouds_")
val clouds: Clouds,
#SerializedName("cod")
val cod: Int,
#Embedded(prefix = "coord_")
val coord: Coord,
#SerializedName("dt")
val dt: Int,
#SerializedName("id")
val id: Int,
#Embedded(prefix = "main_")
val main: Main,
#SerializedName("name")
val name: String,
#Embedded(prefix = "sys_")
val sys: Sys,
#SerializedName("visibility")
val visibility: Int,
#Embedded(prefix = "wind_")
val wind: Wind
) {
#PrimaryKey(autoGenerate = false)
var idKey: Int = CURRENT_WEATHER_ID
}
Weather:
data class Weather(
#SerializedName("description")
val description: String,
#SerializedName("icon")
val icon: String,
#SerializedName("id")
val id: Int,
#SerializedName("main")
val main: String
)
Converter:
class Converters {
#TypeConverter
fun arrayListToJson(value: List<Weather>?): String {
return Gson().toJson(value)
}
#TypeConverter
fun jsonToArrayList(value: String): List<Weather> {
val objects = Gson().fromJson(value, Array<Weather>::class.java) as Array<Weather>
val list = objects.toList()
return list
}
Database:
#Database(entities = [CurrentWeather::class, Location::class], version = 15, exportSchema = false)
#TypeConverters(Converters::class) //converter initialization
abstract class WeatherDatabase : RoomDatabase() {

Here is the modified converter class. It might help you.
object class Converters {
val gson = Gson()
#TypeConverter
fun arrayListToJson(list: List<Weather>?): String? {
return if(list == null) null else gson.toJson(list)
}
#TypeConverter
fun jsonToArrayList(jsonData: String?): List<Weather>? {
return if (jsonData == null) null else gson.fromJson(jsonData, object : TypeToken<List<Weather>?>() {}.type)
}
}

Related

Error of type convertors in room database

I am trying to make a type convertor for a model class in my app. The model class is given below.
Order
#Entity(tableName = "Orders")
data class Order(
#PrimaryKey
var customerId:String,
var companyId:String,
var orderBookerId:String,
#ColumnInfo(name = "items") var list:List<SelectedProductsModel>
)
SelectedProductsModel
data class SelectedProductsModel(
var quantity: Int,
var skuId: String,
var companyId: String,
var productName: String?,
var vendor_brand_name: String,
var purchasePrice: Int,
var image: String,
var position: Int
):Serializable
now as you can see that in the Order class there is a var list:List<SelectedProductsModel>. I want to write a type converter for this list but i keep getting an error
error: cannot find symbol
#androidx.room.TypeConverters(value = {SelectedProductModelConvertor.class})
following is my Room database class
#Database(entities = [VisitedPjpModel::class,Order::class], version = 1)
#TypeConverters(SelectedProductModelConvertor::class)
abstract class RoomDatabaseClass : RoomDatabase()
{
public abstract fun visitedDao(): VisitedPjpDao
public abstract fun orderDao():OrderDao
companion object
{
private var instance: RoomDatabaseClass? = null
fun getInstance(context: Context): RoomDatabaseClass?
{
if (instance == null)
{
synchronized(RoomDatabaseClass::class)
{
instance = Room.databaseBuilder(context, RoomDatabaseClass::class.java, "tarseel_database").allowMainThreadQueries().build()
}
}
return instance
}
}
}
i have tried different implementations of type convertors but iam getting the same error which is mentioned above. following are the implementations of type converotrs that i have tried
class SelectedProductModelConvertor
{
#TypeConverter
fun fromList(value : List<SelectedProductsModel>) = Json.encodeToString(value)
#TypeConverter
fun toList(value: String) = Json.decodeFromString<List<SelectedProductsModel>>(value)
}
class SelectedProductModelConvertor
{
#TypeConverter
fun listToJson(value: List<SelectedProductsModel>) = Gson().toJson(value)
#TypeConverter
fun jsonToList(value: String) = Gson().fromJson(value, Array<SelectedProductsModel>::class.java).toList()
}
class SelectedProductModelConvertor
{
#TypeConverter
fun fromListLangList(value: List<SelectedProductsModel>): String
{
val gson = Gson()
val type = object : TypeToken<List<SelectedProductsModel>>()
{}.type
return gson.toJson(value, type)
}
#TypeConverter
fun toSelectedProductsModelList(value: String): List<SelectedProductsModel>
{
val gson = Gson()
val type = object : TypeToken<List<SelectedProductsModel>>()
{}.type
return gson.fromJson(value, type)
}
}
I have tried all these type convertors but iam getting error. please help me
You cannot have a List/Array for a column.
What you can do, is have a class that holds the List/Array and have a Type Converter for that.
So you could have:-
data class SelectedProductsModelList(
val selectedProductsModelList: List<SelectedProductsModel>
)
Then have :-
#Entity(tableName = "Orders")
data class Order(
#PrimaryKey
var customerId:String,
var companyId:String,
var orderBookerId:String,
#ColumnInfo(name = "items") var list:SelectedProductsModelList //<<<<<<<<<<
)
and TypeConverters that convert from/to a SelectProductsModelList object e.g.
#TypeConverter
fun fromSelectedProductsModelList(selectedProductsModelList: SelectedProductsModelList): String {
return Gson().toJson(selectedProductsModelList)
}
#TypeConverter
fun toSelectedProductsModelList(json: String): SelectedProductsModelList {
return Gson().fromJson(json,SelectedProductsModelList::class.java)
}

Room Typeconverter Map<Int, IntArray>

class MapConverters {
#TypeConverter
fun fromString(value: String): Map<Int, IntArray> {
val mapType = object : TypeToken<Map<Int, IntArray>>() {}.type
return Gson().fromJson(value, mapType)
}
#TypeConverter
fun fromMap(map: Map<Int, IntArray>): String {
val gson = Gson()
return gson.toJson(map)
}
}
#Entity
data class StartGame(
#PrimaryKey(autoGenerate = true) val gameId: Int?,
val gameName: String,
val scoreList: Map<Int, IntArray>
)
#Database(
entities = [StartGame::class, PersonList::class],
version = 1,
exportSchema = false
)
#TypeConverters(MapConverters::class){
...}
I got error
I want to put the Map type variable in Room.
I've tried many ways and tried to apply a typeConvertes.
But it didn't work well.
I'd like you to help me with this.
error: Not sure how to convert a Cursor to this method's return type (java.util.Map<java.lang.Integer, int[]>).
public abstract java.util.Map<java.lang.Integer, int[]> getGameScoreBoardById(int gameId);
#Dao
interface DataDao {
...
#Query("SELECT scoreList FROM StartGame WHERE gameId=:gameId")
#TypeConverters(MapConverters::class)
fun getGameScoreById(gameId: Int): Map<Int, IntArray>
D:\myapp\app_boardgame2\app\build\tmp\kapt3\stubs\debug\com\wonddak\boardmaster\room\DataDao.java:20: error: Not sure how to convert a Cursor to this method's return type (java.util.Map<java.lang.Integer, int[]>).
public abstract java.util.Map<java.lang.Integer, int[]> getGameScoreById(int gameId);
You need to specify which fields uses typeConverters in your model like -
#Entity
data class StartGame(
#PrimaryKey(autoGenerate = true) val gameId: Int?,
val gameName: String,
#TypeConverters(MapConverters::class)
val scoreList: Map<Int, IntArray>
)

How to fix TypeConverter class in Android Room (Kotlin)

I'm using Android Room and I have a problem with it. I made a TypeConverter class (in my case it's ConverterHelper), added annotations #ProvidedTypeConverter, #TypeConverter, and #TypeConverters(ConverterHelper::class) but I get the following error:
java.lang.IllegalArgumentException: Unexpected type converter class com.example.mas_implementation_kotlin.helper.ConverterHelper. Annotate TypeConverter class with #ProvidedTypeConverter annotation or remove this converter from the builder.
Here is my ConverterHelper:
#ProvidedTypeConverter
class ConverterHelper {
#TypeConverter
fun stringToListOfStrings(value: String): ArrayList<String> {
val listType: Type = object : TypeToken<ArrayList<String?>?>() {}.type
return Gson().fromJson(value, listType)
}
#TypeConverter
fun listOfStringsToString(list: List<String>): String {
val gson = Gson()
return gson.toJson(list)
}
#TypeConverter
fun listOfVisitsToString(listOfVisits: List<Visit>): String {
return Gson().toJson(listOfVisits).toString()
}
#TypeConverter
fun stringToListOfVisits(value: String): List<Visit> {
val listOfVisits = object : TypeToken<ArrayList<Visit>>() {}.type
return Gson().fromJson(value, listOfVisits)
}
}
Database:
#Database(
entities = [
Consultant::class,
Doctor::class,
Person::class,
Place::class,
PreparationToTest::class,
Receptionist::class,
Referral::class,
Survey::class,
Technician::class,
Test::class,
TestResult::class,
Visit::class
], version = 1
)
#TypeConverters(ConverterHelper::class)
abstract class AppDatabase : RoomDatabase() {
public abstract fun entitiesDao(): EntitiesDao
}
My Entity:
#Entity
#TypeConverters
data class Visit(
#PrimaryKey val id: String,
#ColumnInfo(name = "visitDate") val visitDate: String,
#ColumnInfo(name = "visitPlaceId") val visitPlaceId: String,
#ColumnInfo(name = "defrayalOfExpenses") val defrayalOfExpenses: String,
#ColumnInfo(name = "additionalInfo") val additionalInfo: String,
#ColumnInfo(name = "personId") val personId: String,
#ColumnInfo(name = "consultantId") val consultantId: String,
#ColumnInfo(name = "receptionistId") val receptionistId: String,
#ColumnInfo(name = "referralId") val referralId: String,
#ColumnInfo(name = "visitsStatus") val visitStatus: String,
#ColumnInfo(name = "testId") val testId: String
)
And this is how i create Db in onCreate method:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
setUI()
database = Room.databaseBuilder(
this,
AppDatabase::class.java,
"database"
)
.addTypeConverter(ConverterHelper::class)
.fallbackToDestructiveMigration()
.build()
fetchDataFromDatabase()
fetchListOfBookedVisitsFromDb()
}
This is how i fetched data from db:
private fun fetchDataFromDatabase() {
val visitAdapter = VisitAdapter(baseContext, this::onClickAction)
lifecycleScope.launch(Dispatchers.IO) {
val entitiesDao = database.entitiesDao()
databaseHelper = DatabaseHelper(entitiesDao)
visitAdapter.setAdapterList(databaseHelper.getPersonVisitModelList())
withContext(Dispatchers.Main) {
binding.mainNewVisitListRecyclerView.apply {
adapter = visitAdapter
layoutManager = LinearLayoutManager(this#MainActivity)
}
}
}
}
Where my DatabaseHelper class has method:
fun getPersonVisitModelList(): List<VisitModel> {
val visitModelList = mutableListOf<VisitModel>()
val personVisitsString = entitiesDao.getAllPatientVisits()
val converterHelper = ConverterHelper()
val personVisitsList = converterHelper.stringToListOfVisits(personVisitsString)
for (visit in personVisitsList) {
visitModelList.add(
VisitModel(
visit.id,
getTestTypeByTestId(visit.testId),
getTestPlaceByPlaceId(visit.visitPlaceId),
visit.visitDate
)
)
}
return visitModelList
}
Do you know how to fix this error? I tried commenting getPersonVisitModelList method because I'm not sure if I can create and use an instance of the ConverterHelper class, but the error still occurs.

Cannot figure out how to save this field into database, save a list of Integer

I have this entity :
#Entity(tableName = "recipes")
data class Recipe(
#PrimaryKey val id: Int,
val name: String,
#TypeConverters(Converters::class)
val categories: List<Int>,
val picture: String,
#Embedded(prefix = "time")
val time: Time,
val people: Int,
val difficulty: Int,
val price: Int,
#Embedded(prefix = "ingredients")
#TypeConverters(Converters::class)
val ingredients: List<Ingredient>,
#Embedded(prefix = "utensils")
#TypeConverters(Converters::class)
val utensils: List<Utensil>,
#Embedded(prefix = "steps")
#TypeConverters(Converters::class)
val steps: List<Step>,
val createdAt: String,
val updatedAt: String
) : Serializable
And when I compile it, I got
Cannot figure out how to save this field into database. You can consider adding a type converter for it.
private final java.util.List<java.lang.Integer> categories = null;
Problem is, I added the TypeConverter, it's in my class Converters :
#TypeConverter
fun fromIntList(value: List<Int>): String {
val gson = Gson()
val type = object : TypeToken<List<Int>>() {}.type
return gson.toJson(value, type)
}
#TypeConverter
fun toIntList(value: String): List<Int> {
val gson = Gson()
val type = object : TypeToken<List<Int>>() {}.type
return gson.fromJson(value, type)
}
It should work since it knows that it should transforma list of Int to strings.
Futhermore, I got this error which I dont know where it can come from, and I have it like 5 times.
Entities and Pojos must have a usable public constructor. You can have an empty
constructor or a constructor whose parameters match the fields (by name and type).
I added the nested class like Ingredient, Step, Ustensil but I dont post the code since it should not be related.

Android Room TypeConverter not working

I'm trying to save some data in my Room database but it keeps showhing me an error, here's the code:
MovieDao.kt
#Dao
interface MoviesDao {
#Query("SELECT * from movie")
fun getAll() : LiveData<List<Movie>>
#Update
fun update(movie: Movie)
#Insert(onConflict = OnConflictStrategy.IGNORE)
fun insert(movie: Movie)
}
MoviesDatabase.kt
#Database(entities = [Movie::class], version = 1, exportSchema = false)
#TypeConverters(TorrentConverter::class, GenreConverter::class)
abstract class MoviesDatabase : RoomDatabase() {
companion object {
private var instance: MoviesDatabase? = null
fun getDatabase(context: Context) : MoviesDatabase{
if(instance == null) {
instance = Room.databaseBuilder(context.applicationContext, MoviesDatabase::class.java,
"movies_database").build()
}
return instance as MoviesDatabase
}
}
abstract fun getMoviesDao() : MoviesDao
}
MovieModels.kt
#Entity(tableName = "movie")
data class Movie(
val url: String,
#PrimaryKey
val imdb_code: String,
val title: String,
val year: Int,
val rating: Float,
val runtime: Int,
#TypeConverters(GenreConverter::class)
val genres: List<String>?,
val synopsis: String,
val yt_trailer_code: String,
val language: String,
val mpa_rating: String,
val medium_cover_image: String,
val large_cover_image: String,
val state: String,
#TypeConverters(TorrentConverter::class)
var torrents: List<Torrent>,
var saved: Boolean = false,
var marked: Boolean = false
) : Serializable
data class Torrent(
val url: String,
val hash: String,
val quality: String,
val seeds: Int,
val peers: Int,
val size: String,
val size_bytes: Long
) : Serializable
TypeConverters.kt
class TorrentConverter {
#TypeConverter
fun toTorrent(json: String): Torrent {
val type = object : TypeToken<Torrent>() {}.type
return Gson().fromJson(json, type)
}
#TypeConverter
fun toJson(torrent: Torrent) = Gson().toJson(torrent)
}
class GenreConverter {
#TypeConverter
fun toGenre(json: String): List<String> {
val type = object : TypeToken<List<String>>() {}.type
return Gson().fromJson(json, type)
}
#TypeConverter
fun toJson(genres: List<String>) = Gson().toJson(genres)
}
the error shows me:
error: Cannot figure out how to save this field into database. You can
consider adding a type converter for it.
private java.util.List torrents;
Can someone please help me to figure out why is this error happening? Thanks alot.
It's happening because your TorrentConverter is returning and getting the wrong types.
The method toTorrent should return a List<Torrent> and the method toJson should receive a List<Torrent>
Try this TypeConverter:
class TorrentConverter {
#TypeConverter
fun toTorrent(json: String): List<Torrent> {
val type = object : TypeToken<List<Torrent>>() {}.type
return Gson().fromJson(json, type)
}
#TypeConverter
fun toJson(torrent: List<Torrent>): String {
val type = object: TypeToken<List<Torrent>>() {}.type
return Gson().toJson(torrent, type)
}
}

Categories

Resources