NoSuchFieldException:尝试在 Android Studio 中类型转换自定义对象时出现 ALL_OBJECT_POOL 错误

问题描述 投票:0回答:1

我正在尝试为我在 Android Studio Java 中制作的自定义对象编写一个简单的对象类型转换器。我的对象称为 MapAnnotationObject,并包含三个由以下对象组成的 ArrayList:Markers、Circles 和 PolyLines,所有这些都是 GoogleMaps 实例上的可绘制对象:

import com.google.android.gms.maps.model.Circle;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;

import java.io.Serializable;
import java.util.ArrayList;

public class MapAnnotationObject implements Serializable {

    ArrayList<Marker> markerList;
    ArrayList<Circle> circleList;
    ArrayList<ArrayList<LatLng>> polyLineList;

    public MapAnnotationObject(){
        markerList = new ArrayList<>();
        circleList = new ArrayList<>();
        polyLineList = new ArrayList<>();
    }

    public void addToMarkerList(Marker marker){markerList.add(marker);}
    public void addToCircleList(Circle circle){circleList.add(circle);}
    public void addToPolyLineList(ArrayList<LatLng> coords){polyLineList.add(coords);}

    public ArrayList<Marker> getMarkerList(){return markerList;}
    public ArrayList<Circle> getCircleList(){return circleList;}
    public ArrayList<ArrayList<LatLng>> getPolyLineList(){return polyLineList;}

    public void removeFromMarkerList(Marker marker){markerList.remove(marker);}
    public Circle removeFromCircleList(Circle circle){
        circleList.remove(circle);
        return circle;
    }

}

我想将此对象存储在 Room 数据库中,为此我利用 Gson 编写了一个对象转换器:

import androidx.room.TypeConverter;
import androidx.room.TypeConverters;

import com.example.coursework_2.objects.GeofenceObject;
import com.example.coursework_2.objects.MapAnnotationObject;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Type;

public class MapAnnotationObjectConverter {

    static Gson gson = new Gson();

    @TypeConverter
    public static MapAnnotationObject stringToMapAnnotationObject(String data){
        if (data == null){
            return new MapAnnotationObject();
        }

        Type mapObjectType = new TypeToken<MapAnnotationObject>() {}.getType();

        return gson.fromJson(data, mapObjectType);
    }

    @TypeConverter
    public static String mapAnnotationObjectToString(MapAnnotationObject mapAnnotationObject){
        return gson.toJson(mapAnnotationObject);
    }
}

数据库中以下列来存储对象:

    @ColumnInfo(name = "map_annotations")
    @TypeConverters(MapAnnotationObjectConverter.class)
    public MapAnnotationObject map_annotations;

但是,每当我尝试添加到 Room 数据库时,都会收到以下错误:

java.lang.AssertionError: AssertionError (GSON 2.8.5): java.lang.NoSuchFieldException: ALL_OBJECT_POOL
Logcat 识别出出现在我的类型转换器中的这一行:
return gson.toJson(mapAnnotationObject);
我真的不知道是什么导致了问题以及如何解决它,任何帮助或指导将不胜感激!

我有第二个自定义对象被实现到数据库中,它使用完全相同的代码,没有任何问题,所以我研究了可能找到一种方法来单独转换所有 ArrayList,但我不确定这是否是正确的过程是否采取行动。

java android gson android-room
1个回答
0
投票

您遇到的问题可能与 Gson 库尝试序列化 MapAnnotationObject 并由于对象的内部结构(包含 ArrayList 和其他复杂结构)而面临困难有关。

一种解决方案是为 Gson 编写自定义 TypeAdapter 来处理 MapAnnotationObject 的序列化和反序列化。以下是如何为 MapAnnotationObject 实现自定义 TypeAdapter 的示例:

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;

public class MapAnnotationObjectTypeAdapter extends TypeAdapter<MapAnnotationObject> {

    @Override
    public void write(JsonWriter out, MapAnnotationObject value) throws IOException {
        out.beginObject();
        out.name("markerList");
        writeList(out, value.getMarkerList());
        out.name("circleList");
        writeList(out, value.getCircleList());
        out.name("polyLineList");
        writeNestedList(out, value.getPolyLineList());
        out.endObject();
    }

    @Override
    public MapAnnotationObject read(JsonReader in) throws IOException {
        MapAnnotationObject mapAnnotationObject = new MapAnnotationObject();
        in.beginObject();
        while (in.hasNext()) {
            String name = in.nextName();
            switch (name) {
                case "markerList":
                    mapAnnotationObject.setMarkerList(readList(in, Marker.class));
                    break;
                case "circleList":
                    mapAnnotationObject.setCircleList(readList(in, Circle.class));
                    break;
                case "polyLineList":
                    mapAnnotationObject.setPolyLineList(readNestedList(in, LatLng.class));
                    break;
                default:
                    in.skipValue();
            }
        }
        in.endObject();
        return mapAnnotationObject;
    }

    private <T> void writeList(JsonWriter out, ArrayList<T> list) throws IOException {
        out.beginArray();
        for (T item : list) {
            gson.toJson(item, item.getClass(), out);
        }
        out.endArray();
    }

    private <T> ArrayList<T> readList(JsonReader in, Class<T> type) throws IOException {
        ArrayList<T> list = new ArrayList<>();
        in.beginArray();
        while (in.hasNext()) {
            list.add(gson.fromJson(in, type));
        }
        in.endArray();
        return list;
    }

    private <T> void writeNestedList(JsonWriter out, ArrayList<ArrayList<T>> nestedList) throws IOException {
        out.beginArray();
        for (ArrayList<T> list : nestedList) {
            writeList(out, list);
        }
        out.endArray();
    }

    private <T> ArrayList<ArrayList<T>> readNestedList(JsonReader in, Class<T> type) throws IOException {
        ArrayList<ArrayList<T>> nestedList = new ArrayList<>();
        in.beginArray();
        while (in.hasNext()) {
            nestedList.add(readList(in, type));
        }
        in.endArray();
        return nestedList;
    }
}

public class MapAnnotationObjectConverter {

    static Gson gson = new GsonBuilder()
            .registerTypeAdapter(MapAnnotationObject.class, new MapAnnotationObjectTypeAdapter())
            .create();

    @TypeConverter
    public static MapAnnotationObject stringToMapAnnotationObject(String data){
        if (data == null){
            return new MapAnnotationObject();
        }

        Type mapObjectType = new TypeToken<MapAnnotationObject>() {}.getType();

        return gson.fromJson(data, mapObjectType);
    }

    @TypeConverter
    public static String mapAnnotationObjectToString(MapAnnotationObject mapAnnotationObject){
        return gson.toJson(mapAnnotationObject);
    }
}

这样,您就可以显式定义 Gson 如何序列化和反序列化您的复杂对象,并处理 ArrayList 及其内容。这可能会解决您面临的 NoSuchFieldException 问题。

© www.soinside.com 2019 - 2024. All rights reserved.