I'm trying to save a List of Double to Room database using this Converter class:
public class Converters {
@TypeConverter
public static String fromDoubleList(List<Double> doubleList){
Gson gson = new Gson();
String json = gson.toJson(doubleList);
return json;
}
public static List<Double> fromString(String value){
Type listType = new TypeToken<List<Double>>(){}.getType();
return new Gson().fromJson(value, listType);
}
}
but I keep getting this message:
error: Cannot figure out how to save this field into database. You can consider adding a type converter for it.
Why isn't the converter class working?
Edit - This is my database:
@Database(entities = {MarketUnit.class}, version = 1)
@TypeConverters({Converters.class})
public abstract class MarketDatabase extends RoomDatabase {
public static final String DATABASE_NAME = "market_db";
private static MarketDatabase instance;
public static MarketDatabase getInstance(final Context context){
if(instance == null){
instance = Room.databaseBuilder(
context.getApplicationContext(),
MarketDatabase.class,
DATABASE_NAME
).build();
}
return instance;
}
public abstract MarketDao getMarketDao();
}
I've tried the suggestion from the duplicate question, but it's not working!
CodePudding user response:
In short you cannot have an Array/List directly as a column.
What you can do is have a POJO as a holder class and then have the column use that type.
e.g.
class Holder() {
List<Double> doubleList;
}
and in the Entity class have something like
Holder theColumn;
Noting that the Type Converter would then be from/to Holder
e.g. :-
class Converters {
@TypeConverter
public String fromHolder(Holder h) {
Gson gson = new Gson();
String json = gson.toJson(h);
return json;
}
@TypeConverter
public Holder toHolder(String s) {
return new Gson().fromJson(s, Holder.class);
}
}
Working Example:
Holder :-
class Holder {
public List<Double> doubles;
}
MarketUnit :-
@Entity
class MarketUnit {
@PrimaryKey
Long id = null;
Holder doubleList;
}
Converters :-
class Converters {
@TypeConverter
public static String fromHolder(Holder h) {
Gson gson = new Gson();
String json = gson.toJson(h);
return json;
}
@TypeConverter
public static Holder toHolder(String s) {
return new Gson().fromJson(s, Holder.class);
}
}
- made static so can be called
MarketDao :-
@Dao
abstract class MarketDao {
@Insert
abstract long insert(MarketUnit marketUnit);
@Query("SELECT * FROM marketunit")
abstract List<MarketUnit> getAllMarketUnits();
}
MarketDatabase :-
@Database(entities = {MarketUnit.class}, version = 1)
@TypeConverters({Converters.class})
public abstract class MarketDatabase extends RoomDatabase {
public static final String DATABASE_NAME = "market_db";
private static MarketDatabase instance;
public static MarketDatabase getInstance(final Context context){
if(instance == null){
instance = Room.databaseBuilder(
context.getApplicationContext(),
MarketDatabase.class,
DATABASE_NAME
).allowMainThreadQueries().build();
}
return instance;
}
public abstract MarketDao getMarketDao();
}
- .allowMainThreadQueries added for brevity and convenience
Finally an Activity MainActivity for test:-
public class MainActivity extends AppCompatActivity {
MarketDatabase db;
MarketDao dao;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
db = MarketDatabase.getInstance(this);
dao = db.getMarketDao();
MarketUnit mu1 = new MarketUnit();
Holder h = new Holder();
ArrayList<Double> dbls = new ArrayList<>();
dbls.add(200.01);
dbls.add(111.111);
h.doubles = dbls;
mu1.doubleList = h;
dao.insert(mu1);
for(MarketUnit mu: dao.getAllMarketUnits()) {
Log.d("DBINFO","MarketUnit ID = " mu.id);
Log.d("DBINFO","Converted Holder :-\n\t" Converters.fromHolder(mu.doubleList));
for(Double d: mu.doubleList.doubles) {
Log.d("DBINFO","\tDouble is " d);
}
}
}
}
Result from the Log :-
2021-11-12 16:34:37.776 D/DBINFO: MarketUnit ID = 1
2021-11-12 16:34:37.777 D/DBINFO: Converted Holder :-
{"doubles":[200.01,111.111]}
2021-11-12 16:34:37.777 D/DBINFO: Double is 200.01
2021-11-12 16:34:37.777 D/DBINFO: Double is 111.111
The MarketUnit table using App Inspection :-