You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Room数据库LiveData计算异常:ArrayList类型转换错误求助

问题:Room存储ArrayList时Gson解析异常

场景说明

需要在Room数据库中用两个ArrayList存储数据,实现了Entity、TypeConverter、DAO和数据插入逻辑,但运行时抛出解析异常,无法正常读取数据。

Entity类

@Entity
public class User {

    public int getId() {
        return id;
    }

    @NonNull
    public ArrayList<String> getValues(){
        return values;
    }

    @NonNull
    public ArrayList<String> getDates(){
        return dates;
    }

    @NonNull
    public String getType_counter() {
        return type_counter;
    }

    @NonNull
    public String getWhere_counter() {
        return where_counter;
    }

    @PrimaryKey(autoGenerate = true)
    public int id;

    @ColumnInfo(name = "d")
    @TypeConverters({Converters.class})
    public ArrayList<String> dates;                   // arraylist here

    @ColumnInfo(name = "value")
    @TypeConverters({Converters.class})
    public ArrayList<String> values;                  // arraylist here

    @ColumnInfo(name = "type")
    public String type_counter;

    @ColumnInfo(name = "location")
    public String where_counter;
}

TypeConverter类

public class Converters {
    @TypeConverter
    public static ArrayList<String> fromString(String value) {
        Type listType = new TypeToken<ArrayList<String>>() {}.getType();
        return new Gson().fromJson(value, listType);
    }

    @TypeConverter
    public static String fromArrayList(ArrayList<String> list) {
        Gson gson = new Gson();
        return gson.toJson(list);
    }
}

数据插入方法

private void saveNewValue(String value, String type, String location){

        // Getting current date
        Date c = Calendar.getInstance().getTime();
        SimpleDateFormat df = new SimpleDateFormat("dd-MMM-yyyy", Locale.getDefault());
        String formattedDate = df.format(c);

        //Saving new User
        userViewModel = ViewModelProviders.of(this).get(UserViewModel.class);

        User user = new User();
        user.values.add(value);
        user.dates.add(formattedDate);
        user.type_counter = type;
        user.where_counter = location;

        userViewModel.insert(user);

        Toast.makeText(this, "Successfully saved!", Toast.LENGTH_SHORT).show();
    }

DAO类

@Dao
public interface UserDao {

    @Query("SELECT * FROM User ")
    LiveData<List<User>> getAllValues();

    @Insert
    void insertValue(User ... users);

    @Delete
    void deleteValue(User user);

    @Query("SELECT location FROM User")
    LiveData<String[]> getAllLocations();

    @Query("SELECT * from User WHERE id=:id")
    LiveData<User> getUserWithId(int id);

}

运行时异常信息

E/AndroidRuntime: FATAL EXCEPTION: arch_disk_io_0
    Process: org.tensorflow.lite.examples.detection, PID: 14774
    java.lang.RuntimeException: Exception while computing database live data.
        at androidx.room.RoomTrackingLiveData$1.run(RoomTrackingLiveData.java:92)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
        at java.lang.Thread.run(Thread.java:764)
     Caused by: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 1 path $
        at com.google.gson.Gson.fromJson(Gson.java:944)
        at com.google.gson.Gson.fromJson(Gson.java:897)
        at com.google.gson.Gson.fromJson(Gson.java:846)
        at org.tensorflow.lite.examples.detection.Converters.fromString(Converters.java:15)
        at org.tensorflow.lite.examples.detection.db.UserDao_Impl$3.call(UserDao_Impl.java:126)
        at org.tensorflow.lite.examples.detection.db.UserDao_Impl$3.call(UserDao_Impl.java:109)
        at androidx.room.RoomTrackingLiveData$1.run(RoomTrackingLiveData.java:90)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636) 
        at java.lang.Thread.run(Thread.java:764) 
     Caused by: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 1 path $
        at com.google.gson.stream.JsonReader.beginArray(JsonReader.java:351)
        at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:80)
        at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61)
        at com.google.gson.Gson.fromJson(Gson.java:932)
        at com.google.gson.Gson.fromJson(Gson.java:897) 
        at com.google.gson.Gson.fromJson(Gson.java:846) 
        at org.tensorflow.lite.examples.detection.Converters.fromString(Converters.java:15) 
        at org.tensorflow.lite.examples.detection.db.UserDao_Impl$3.call(UserDao_Impl.java:126) 
        at org.tensorflow.lite.examples.detection.db.UserDao_Impl$3.call(UserDao_Impl.java:109) 
        at androidx.room.RoomTrackingLiveData$1.run(RoomTrackingLiveData.java:90) 
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636) 
        at java.lang.Thread.run(Thread.java:764) 
D/OpenGLRenderer: endAllActiveAnimators on 0x72aa705400 (RippleDrawable) with handle 0x72a70ea8e0

问题原因及修复方案

核心问题

  1. ArrayList未初始化:创建User对象时,dates和values字段未初始化,直接调用add()会触发空指针,且Room会将未初始化的@NonNull字段存储为空字符串,导致Gson读取时无法解析成数组。
  2. TypeConverter未处理null/空字符串:转换器没有处理输入为null或空字符串的场景,Gson无法将空字符串解析为ArrayList。
  3. TypeConverters注解位置错误:注解放在Entity字段上可能导致全局生效异常,应放在Database类上。

修复步骤

1. 初始化User类的ArrayList字段

修改User类,在字段声明或构造方法中初始化ArrayList,同时保留Room所需的无参构造:

@Entity
public class User {

    // ... 原有getter方法 ...

    @PrimaryKey(autoGenerate = true)
    public int id;

    @ColumnInfo(name = "d")
    public ArrayList<String> dates = new ArrayList<>();

    @ColumnInfo(name = "value")
    public ArrayList<String> values = new ArrayList<>();

    @ColumnInfo(name = "type")
    public String type_counter;

    @ColumnInfo(name = "location")
    public String where_counter;

    // Room需要的无参构造
    public User() {
        this.dates = new ArrayList<>();
        this.values = new ArrayList<>();
    }
}

2. 完善TypeConverter的空值处理

修改Converters类,增加null和空字符串的判断逻辑:

public class Converters {
    @TypeConverter
    public static ArrayList<String> fromString(String value) {
        if (value == null || value.isEmpty()) {
            return new ArrayList<>();
        }
        Type listType = new TypeToken<ArrayList<String>>() {}.getType();
        return new Gson().fromJson(value, listType);
    }

    @TypeConverter
    public static String fromArrayList(ArrayList<String> list) {
        if (list == null) {
            return new Gson().toJson(new ArrayList<String>());
        }
        Gson gson = new Gson();
        return gson.toJson(list);
    }
}

3. 迁移TypeConverters注解到Database类

在Room数据库类上添加注解,确保全局生效:

@Database(entities = {User.class}, version = 1)
@TypeConverters({Converters.class})
public abstract class AppDatabase extends RoomDatabase {
    public abstract UserDao userDao();
}

4. 清理旧数据库

卸载应用重新安装,或添加数据库迁移逻辑,避免读取之前存储的无效数据。

验证

修复后重新运行,插入数据后查询,可正常解析ArrayList,不再抛出解析异常。

内容的提问来源于stack exchange,提问作者ALiCe P.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 22:45:38