Android使用Room Persistence Library存储含对象的ArrayList求助
解决Room保存WeekViewEvent列表的问题
嘿,我来帮你搞定这些Room相关的疑问,一步步来:
1. 使用TypeConverter后,加载的ArrayList还能正常用吗?
完全可以!只要你的TypeConverter能正确把ArrayList<WeekViewEvent>序列化成Room支持的类型(比如String),再从这个类型反序列化回原对象列表,那么加载后的列表和你原来的mNewEvents没有任何区别——里面的每个WeekViewEvent对象的属性都会完整保留,你照样可以像之前一样调用getName()、setId(),也能直接传给日历库使用。
2. 你写的@Entity类可行吗?
不行哦,这里有个关键问题:Room的@PrimaryKey不能是集合类型。主键需要是单个的、能唯一标识实体的简单类型(比如int、long、String),而你把ArrayList作为主键,Room根本无法处理。
咱们得修改Entity类,给它加一个单独的主键,把事件列表作为普通字段:
@Entity public class EventList { // 用自增的int作为主键,Room需要这个来管理实体 @PrimaryKey(autoGenerate = true) private int id; // 要保存的事件列表,后续用TypeConverter处理 private ArrayList<WeekViewEvent> events; // 构造函数、getter和setter public EventList(ArrayList<WeekViewEvent> events) { this.events = events; } public int getId() { return id; } public void setId(int id) { this.id = id; } public ArrayList<WeekViewEvent> getEvents() { return events; } public void setEvents(ArrayList<WeekViewEvent> events) { this.events = events; } }
3. 怎么写@TypeConverter实现列表的保存与读取?
既然你已经能用GSON序列化单个WeekViewEvent,那扩展到列表就很简单了,只需要借助TypeToken来告诉GSON要转换的集合类型。
第一步:编写TypeConverter类
import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import java.lang.reflect.Type; import java.util.ArrayList; public class EventListConverter { // 初始化Gson实例,建议全局复用 private static final Gson gson = new Gson(); // 把字符串转成ArrayList<WeekViewEvent> @TypeConverter public static ArrayList<WeekViewEvent> fromJsonString(String json) { // TypeToken用来获取泛型类型的Type对象 Type listType = new TypeToken<ArrayList<WeekViewEvent>>() {}.getType(); return gson.fromJson(json, listType); } // 把ArrayList<WeekViewEvent>转成字符串 @TypeConverter public static String toJsonString(ArrayList<WeekViewEvent> events) { return gson.toJson(events); } }
第二步:在Room数据库中注册转换器
需要在你的Database类上加上@TypeConverters注解,告诉Room使用这个转换器:
import androidx.room.Database; import androidx.room.RoomDatabase; import androidx.room.TypeConverters; @Database(entities = {EventList.class}, version = 1) @TypeConverters({EventListConverter.class}) public abstract class AppDatabase extends RoomDatabase { // 定义Dao接口的抽象方法 public abstract EventListDao eventListDao(); }
第三步:编写Dao接口操作数据库
比如我们只需要保存一个事件列表,那么Dao可以这样写:
import androidx.room.Dao; import androidx.room.Insert; import androidx.room.Query; @Dao public interface EventListDao { // 插入事件列表 @Insert void insertEventList(EventList eventList); // 查询保存的事件列表(因为只存一个,所以取第一条) @Query("SELECT * FROM EventList LIMIT 1") EventList getSavedEventList(); }
第四步:使用示例
保存列表的时候:
// 把你的mNewEvents包装成EventList对象 EventList eventList = new EventList(mNewEvents); // 插入数据库(注意要在子线程执行,或者用Coroutines/AsyncTask) appDatabase.eventListDao().insertEventList(eventList);
读取列表的时候:
// 从数据库获取EventList EventList savedEventList = appDatabase.eventListDao().getSavedEventList(); // 拿到原来的ArrayList<WeekViewEvent>,直接用就行 ArrayList<WeekViewEvent> loadedEvents = savedEventList.getEvents();
这样加载后的loadedEvents就和你原来的mNewEvents完全一样,可以直接传给日历库使用啦!
内容的提问来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

